接下来是golang重头戏之二channel,上一篇已经有讲过gorotuine,channel的用途非常多,可以拿来当不同gorotuine的沟通信道,也可以buffer quene,那接下来开始介绍channel
channel
首先我们要先来试试看,如何宣告一个channel,并且传送一个信息给它
package main
import(
“fmt”
)
var message chan string
func Bot(){
msg:= <-message
fmt.Printf(“Bot Print:%s\n”,msg)
}
func main(){
message = make(chan string)
go Bot()
message <-“Hello World”
fmt.Println(“end”)
}
https://play.golang.org/p/kdVCn2Abk11
channel如果没有宣告buffer,sender端,送进去的信息,reciver端没收之前,sender端送不进去第二则信息,此时,sender端会block,在这边要注意控制这个问题,以避免造成deadlock。
下面我们示范一下deadlock情境(talktoyourpresident)
package main
import(
“fmt”
)
var message chan string
func Bot(){
msg:= <-message
fmt.Printf(“Bot Print:%s\n”,msg)
}
func main(){
message = make(chan string)
go Bot()
message <-“first message”
fmt.Println(“first message send finish”)
message <-“second message”
fmt.Println(“second message send finish”)
fmt.Println(“end”)
}
https://play.golang.org/p/O_DjamN8sss
那如何在没宣告buffer的情况下,排除上面的deadlock
package main
import(
“fmt”
“time”
)
var message chan string
func Bot(){
//让bot不断接收信息,就不会造成main thread卡死
for msg:= range message {
fmt.Printf(“Bot Print:%s\n”,msg)
}
}
func main(){
message = make(chan string)
go Bot()
message <-“first message”
fmt.Println(“first message send finish”)
message <-“second message”
fmt.Println(“second message send finish”)
//加入Sleep是为了避免main thread提前结束,而看不到bot后续印的值
time.Sleep(1*time.Second)
fmt.Println(“end”)
}
https://play.golang.org/p/OSzlVjXGMIj
那如何宣告channel的buffer呢?
package main
import(
“fmt”
)
var message chan string
func Bot(){
msg:= <-message
fmt.Printf(“Bot Print:%s\n”,msg)
}
func main(){
//这里为宣告5个channel buffer,意思就是可以quene 5个string
message = make(chan string,5)
go Bot()
message <-“first message”
fmt.Println(“first message send finish”)
message <-“second message”
fmt.Println(“second message send finish”)
fmt.Println(“end”)
}
https://play.golang.org/p/NpBkrnKGfIQ
由上面可以看到,运用buffer宣告也可以解决前面示例deadlock的问题。
Do not communicate by sharing memory;instead,share memory by communicating.
上面这句话,是引言自,golang官方blog,有一篇讲解channel的使用时机、跟他的设计精神,有兴趣的可以前往阅读(mjjpassion)。