[英]How to write functions that are executed in goroutines to send and receive messages?
[英]How do chained functions get executed as goroutines?
鑒於這個游樂場 :
package main
import "fmt"
func main() {
go oneFunc().anotherFunc()
}
func oneFunc() something {
fmt.Println("oneFunc")
return something{}
}
type something struct{}
func (s something) anotherFunc() {
fmt.Println("anotherFunc")
}
為什么輸出:
oneFunc
並且“anotherFunc”從未打印過?
anotherFunc
不執行,直到oneFunc
返回一個值。 因此,程序在anotherFunc
能夠運行之前退出。 您需要等待anotherFunc
在main
退出之前運行。
您可以通過Go頻道完成此操作。 例如:
http://play.golang.org/p/dWoLB9afSj
package main
import "fmt"
func main() {
ch := make(chan int)
go oneFunc(ch).anotherFunc()
fmt.Println("Waiting...")
<-ch
fmt.Println("Done.")
}
func oneFunc(ch chan int) something {
fmt.Println("oneFunc")
return something{ch}
}
type something struct{
ch chan int
}
func (s something) anotherFunc() {
fmt.Println("anotherFunc")
s.ch <- 1
}
評估go
關鍵字后面的表達式,然后同時執行該表達式的函數值。
因此,在您的示例中, oneFunc()
,因此oneFunc
輸出,並且返回實例上的方法anotherFunc
被並發調用。 但是,您的程序會在goroutine運行之前終止,這就是您沒有看到打印了anotherFunc
。
解決方案:使用sync.WaitGroup
或通道進行同步。
要實際(憑經驗)驗證您的go
調用同時執行anotherFunc
而不是 oneFunc
您可以在每個函數中打印堆棧並比較輸出。 示例( 正在播放 ):
var wg = sync.WaitGroup{}
func main() {
wg.Add(1)
go oneFunc().anotherFunc()
wg.Wait()
}
func oneFunc() something {
fmt.Println("oneFunc")
buf := make([]byte, 4096)
runtime.Stack(buf, false)
fmt.Println("Stack of oneFunc:", string(buf))
return something{}
}
type something struct{}
func (s something) anotherFunc() {
defer wg.Done()
buf := make([]byte, 4096)
runtime.Stack(buf, false)
fmt.Println("Stack of anotherFunc:", string(buf))
fmt.Println("anotherFunc")
}
你會看到這樣的事情:
oneFunc
Stack of oneFunc: goroutine 1 [running]:
main.oneFunc()
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:20 +0x118
main.main()
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:11 +0x50
Stack of anotherFunc: goroutine 2 [running]:
main.something.anotherFunc()
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:32 +0xb2
created by main.main
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:11 +0x69
anotherFunc
堆棧跟蹤甚至告訴您這兩個函數在不同的goroutine中運行,不需要比較方法調用。
我喜歡它的方式就是這樣, go
-like defer
- 在行上消耗最后一次調用或對括號,並且將不按順序調用該函數。 之前的每次調用都是同步的。
go
使得調用並發。 並defer
延遲調用,直到當前函數返回。
在Effective Go的defer
部分中有一個非常好的例子
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.