简体   繁体   中英

Run goroutine with buffered channel, I got an output before input an element into an channel

package main

import (
    "fmt"
    "time"
)

func send(ch chan int, size int) {
    for i := size; i < size+10; i++ {
        ch <- i
        fmt.Printf("put val %v in channel\n", i)
    }
    // close(ch)
}

func main() {
    ch1 := make(chan int, 2)
    ch2 := make(chan int, 1)
    // defer close(ch1)
    // defer close(ch2)

    go send(ch1, 0)
    go send(ch2, 20)

    time.Sleep(time.Second)

    for {
        select {
        case val := <-ch1:
            fmt.Printf("read val %v from chl\n", val)
        case val := <-ch2:
            fmt.Printf("read val %v from ch2\n", val)
        case <-time.After(2 * time.Second): //这里是从阻塞的channel中超时返回的小技巧
            fmt.Println("Time out")
            return
        }
    }

}

I run this code, and I got read val 2 from chl before put val 2 in channel . I don't know how it comes from. It's seem reasonable to read after put new value in channel1.

An example of output is:

put val 20 in channel
put val 0 in channel
put val 1 in channel
put val 2 in channel
read val 0 from chl
read val 1 from chl
read val 20 from ch2
read val 21 from ch2
put val 3 in channel
put val 21 in channel
put val 22 in channel
read val 2 from chl
read val 3 from chl
read val 4 from chl
read val 22 from ch2
read val 23 from ch2
put val 4 in channel
put val 5 in channel
put val 6 in channel
put val 7 in channel
read val 5 from chl
read val 6 from chl
read val 7 from chl
read val 8 from chl
put val 8 in channel
put val 9 in channel
read val 9 from chl
put val 23 in channel
put val 24 in channel
put val 25 in channel
read val 24 from ch2
read val 25 from ch2
put val 26 in channel
put val 27 in channel
read val 26 from ch2
read val 27 from ch2
read val 28 from ch2
put val 28 in channel
put val 29 in channel
read val 29 from ch2
Time out

in your send() function, the line fmt.Printf("put val %v in channel\\n", i) is executed after a value has been send to the buffered channel Since you are running this in a goroutine, it is possible that the loop receives value before the goroutine can print the value, because goroutines run concurrently. Concurrently means it may be parallel, maybe not. This makes it unpredictable in terms of order of execution (for the spawned goroutines), but guarantees completion
Side note: Sending a value to a buffered channel blocks in case the channel is full, hence your code has more than one possible source for the behavior displayed, in case this occurs when the buffer is full (maybe for other numbers in the loop), although not guaranteed to happen

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM