理解golang中关键字-chan&select

网友投稿 289 2022-08-29

理解golang中关键字-chan&select

chan

channel直译过来就是管道,chan关键字定义了goroutine中的管道通信,一个goroutine可以和另一个goroutine进行通信。

chan的读写和定义如下:

//define a chan type variablevar ch chan int = make(chan int, 10);//orch := make(chan int, 10);//write data into chan ch <- 1;ch <- 2;//read data from chan var x int;x = <-ch;x = <-ch;

看下面这段代码,其中x获取ch队头值,nonempty返回ch是否非空的:

func main() { var ch chan int = make(chan int, 10) ch <- 1 ch <- 2 ch <- 3 close(ch) var x int var nonempty bool x, nonempty = <-ch fmt.Println("x =", x, " length of ch is", len(ch), "nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, " length of ch is", len(ch), "nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, " length of ch is", len(ch), "nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, " length of ch is", len(ch), "nonempty", nonempty)}

打印结果:

可以看到chan是类似队列的先进先出类型,每次读出一个数据后,ch自动弹出该数据不再保存。

chan一定要初始化才能进行读写操作,否则产生死锁:

package mainimport ( "fmt")func main() { var ch chan int// = make(chan int, 10) ch <- 1 ch <- 2 ch <- 3 close(ch) var x int var nonempty bool x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty)}

执行结果,由于所有goroutine已经睡眠,产生死锁:

select

select会执行第一个可以执行的case语句,会一直监听直到有第一个可以执行的语句。或者换一种说法,select就是用来监听和channel有关的IO操作,当 IO 操作发生时,触发相应的动作。

看这段代码:

package mainimport ( "fmt" "time")func main() { var ch chan int = make(chan int, 10) var x int = 0 var nonempty bool go func() { ch <- 1 ch <- 2 ch <- 3 close(ch) x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty) x, nonempty = <-ch fmt.Println("x =", x, ", length of ch is", len(ch), ", nonempty", nonempty) }() select { case ch <- x: fmt.Println("ch write", x) case x = <-ch: fmt.Println("ch read", x) default: fmt.Println("nothing to do") } time.Sleep(time.Second)}

执行结果,写入0:

注释掉第一个case:

select { // case ch <- x: // fmt.Println("ch write", x) case x = <-ch: fmt.Println("ch read", x) default: fmt.Println("nothing to do") }

执行结果,由于ch为空无法读出,运行default:

如果有多个io操作都可以执行的话,select会随机选择一个执行:

select { // case ch <- x: // fmt.Println("ch write", x) case ch <- 4: fmt.Println("ch write 4") case ch <- 5: fmt.Println("ch write 5") case x = <-ch: fmt.Println("ch read", x) default: fmt.Println("nothing to do") }

两种结果:

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:地产营销,现在还能做些什么?!(地产营销做什么的)
下一篇:聊聊golang中的锁
相关文章

 发表评论

暂时没有评论,来抢沙发吧~