用Go语言进行 spawn(派生)和 channel(通道)的操作
在之前的帖子中,我尝试了Crystal。在这个链接中:http://qiita.com/tabetomo/items/754308a6cd48bcf56585
我试着用elixir的spawn和channel来进行发送和接收操作。现在我将用相同的方法在golang中尝试一下。
以下是Crystal编程示例和执行示例。
ch1 = Channel(String).new(1)
ch2 = Channel(String).new(1)
done = Channel(Bool).new()
spawn do
puts ch1.receive
puts ch2.receive
puts ch1.receive
done.send(true) # end
end
spawn do
ch1.send("apple")
ch2.send("orange")
end
ch1.send("grape")
done.receive
$ crystall spawn3.cr
grape
orange
apple
在Go中生成(goroutine)
同一件事情在go中的进行过程过于简单了。当我用crystal写的时候也有同样的感觉,太过轻松了。
package main
import "fmt"
func main() {
ch1 := make(chan string, 1)
ch2 := make(chan string, 1)
done := make(chan bool, 0)
go func() {
msg := <-ch1
fmt.Println(msg)
msg = <-ch2
fmt.Println(msg)
msg = <-ch1
fmt.Println(msg)
done <- true
}()
go func() {
ch1 <- "apple"
ch2 <- "orange"
}()
ch1 <- "grape"
<-done
}
实施案例
$ go run spawn3.go
grape
orange
apple
备注;关于上述程序,如果不加入等待(done)的话,在显示grape时程序会立即结束。
在Go语言中,发生死锁会产生错误吗?
好吧,一开始我们在crystal中使用尺寸为0的通道进行操作。
ch1 = Channel(String).new
ch2 = Channel(String).new
略
在这种情况下,直到接收到通道后,发送方的处理才能继续进行(换句话说,发送方可以阻塞并等待接收)。如果将通道的大小设为0,上述程序将显示”grape”并发生死锁(直到按下Ctrl-C之前,处理不会返回)。
然而,在之前的帖子评论中,有人指出使用”go”会导致错误。我打算试一下。
package main
import "fmt"
func main() {
ch1 := make(chan string, 0)
ch2 := make(chan string, 0)
略
普通にgoでもサイズ0のstringチャネルを作成することができます(ビルドもできて動作もします)。ここまでは問題ありません。ただし、
执行实例
$ go build spawn3.go
$ ./spawn3
grape
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:23 +0x143
goroutine 5 [chan receive]:
main.main.func1(0xc42001a0c0, 0xc42001a120, 0xc42001a180)
/Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:12 +0x145
created by main.main
/Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:17 +0xbb
goroutine 6 [chan send]:
main.main.func2(0xc42001a0c0, 0xc42001a120)
/Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:19 +0x5a
created by main.main
/Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:21 +0xe7
当在Go语言中显示grape时,会检测到死锁并导致运行时错误(fatal error: all goroutines are asleep – deadlock!)。我不知道这是好还是坏,但是当所有goroutines都处于休眠状态时,无法做任何处理,所以结束可能更好。