我正在学习Go lang'参观Go'并且很难理解Go频道的运行顺序,
package main
import "fmt"
import "time"
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
time.Sleep(1000 * time.Millisecond)
sum += v
}
c <- sum // send sum to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
fmt.Println("Print this first,")
}
如果在代码上方运行,我预计,
Print this first,
17 -5 12
因为,Go例程以非阻塞方式运行,但是,实际上是打印,
17 -5 12
Print this first,
我在互联网上找到的另一个例子,
package main
import "fmt"
type Data struct {
i int
}
func func1(c chan *Data ) {
fmt.Println("Called")
for {
var t *Data;
t = <-c //receive
t.i += 10 //increment
c <- t //send it back
}
}
func main() {
c := make(chan *Data)
t := Data{10}
go func1(c)
println(t.i)
c <- &t //send a pointer to our t
i := <-c //receive the result
println(i.i)
println(t.i)
}
另外,我预计,它打印&#34;被叫&#34;首先,但结果是
10
20
20
Called
我误解了什么?请帮助我了解Go例程和频道。
答案 0 :(得分:3)
在您的第一个示例中,x, y := <-c, <-c
会阻止,直到它读取c
两次,然后将值分配给x, y
。除了通道,你有一个赋值,一个print语句,然后是另一个print语句。这些都是同步的东西,并且会按照你说明的顺序发生。第二个打印语句无法首先打印。
第二个是因为fmt.Println
写入STDOUT而println
写入STDERR。如果你是一致的(比如在任何地方使用println
),你会看到:
10
Called
20
20
这是因为主要的第一个println(t.i)
和goroutine中发生的println("Called")
之间存在竞争。我猜测GOMAXPROCS
设置为1,这将始终如一地发生。将GOMAXPROCS
设置为NumCPU
后,我会得到一些结果,有时看起来像上面那样,有时候会像这样:
10Called
20
20