Using len(ch) like this in a concurrency scenario is a big no because then the value you get carries 0 bits of useful information. It's not a data race, it's worse, the race is semantic and not fixable without removing the use of len(ch).
On Sun, Aug 28, 2016, 17:26 dc0d <kaveh.shahbaz...@gmail.com> wrote: > TL;DR > > Does assigning a (buffered) channel, already in a variable, to a second > variable, affects the result of len function? > > Long version: > What is happening here? - Code at the end; Go 1.7. > > *Output 1*: > > Nine times: > [ info ] 2016/08/28 19:51:28 LEN_BEFORE=0 > > [ info ] 2016/08/28 19:51:28 LEN=7 > > [ info ] 2016/08/28 19:51:28 S00=7 > > But if the second case gets commented like this: > > case <-limiter.C: > // if len(actualBuffer) > 0 { > // buffer = actualBuffer > // } else { > // buffer = nil > // } > > It works as expected; *Output2*: > > [ info ] 2016/08/28 19:54:28 LEN_BEFORE=0 > > [ info ] 2016/08/28 19:54:28 LEN=7 > > [ info ] 2016/08/28 19:54:28 S00=7 > > [ info ] 2016/08/28 19:54:29 LEN_BEFORE=7 > > [ info ] 2016/08/28 19:54:30 LEN_BEFORE=7 > > [ info ] 2016/08/28 19:54:31 LEN_BEFORE=7 > > [ info ] 2016/08/28 19:54:32 LEN_BEFORE=7 > > [ info ] 2016/08/28 19:54:33 LEN_BEFORE=7 > > [ info ] 2016/08/28 19:54:34 LEN_BEFORE=7 > > [ info ] 2016/08/28 19:54:35 LEN_BEFORE=7 > > [ info ] 2016/08/28 19:54:36 LEN_BEFORE=7 > ... > > Code: > > package main > > > import ( > "log" > "time" > > > "github.com/comail/colog" > ) > > > func status00Channeler() { > <-start > > > limiter := time.NewTicker(time.Second / maxMsgPerSec) > fetchLimiter := time.NewTicker(time.Second) > > > var buffer chan *Data > actualBuffer := make(chan *Data, maxMsgPerSec) > db, err := newDB() > if err != nil { > log.Panic(err) > } > > > FIRST: > for { > select { > case <-interrupted: > break FIRST > case <-limiter.C: > // if len(actualBuffer) > 0 { > // buffer = actualBuffer > // } else { > // buffer = nil > // } > case i := <-buffer: > select { > case status00 <- i: // will block here > case <-interrupted: > break FIRST > } > case <-fetchLimiter.C: > log.Printf("LEN_BEFORE=%d", len(actualBuffer)) > if len(actualBuffer) > 0 { > continue > } > > > s00, err := db.GetIncomings() > if err != nil { > log.Println(`error:`, err) > time.Sleep(time.Second) > continue > } > if s00 == nil || len(s00) == 0 { > continue > } > > > FILL_BUFFER: > for _, v := range s00 { > select { > case actualBuffer <- v: > default: > break FILL_BUFFER > } > } > > > log.Printf("LEN=%d", len(actualBuffer)) > log.Printf("S00=%d", len(s00)) > } > } > } > > > func main() { > go status00Channeler() > close(start) > > > <-time.After(time.Second * 30) > } > > > var ( > status00 = make(chan *Data, maxMsgPerSec) > ) > > > type Data struct{} > > > const ( > maxMsgPerSec = 60 > ) > > > func newDB() (*DB, error) { > res := new(DB) > return res, nil > } > > > func (db *DB) GetIncomings() ([]*Data, error) { > var res []*Data > res = append(res, &Data{}) > res = append(res, &Data{}) > res = append(res, &Data{}) > res = append(res, &Data{}) > res = append(res, &Data{}) > res = append(res, &Data{}) > res = append(res, &Data{}) > > > return res, nil > } > > > type DB struct{} > > > func init() { > colog.Register() > } > > > var ( > start = make(chan struct{}) > interrupted = make(chan struct{}) // comes from sys interrupts SIGINT, > SIGTERM, etc > ) > > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- -j -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.