转载

Channels in Go range and select

这是Channels in go的第二篇,这篇主要讲range and select ,第一篇可以打开这个链接 https://xiequan.info/channels-in-go/ 。

接收Channle的数据的时候我们会遇到,什么时候需要停止等待数据。有更多数据,还是已经全部完成?我们是继续等待还是继续?一种方法就是不断的轮询和检查通道是否已经关闭,但是这种方法并不是特别有效。

Channels and range

Go提供了range关键词,当它与Channel 一起使用的时候他会等待channel的关闭。

package main                                                                                             import (     "fmt"     "time"     "strconv" )   funcmakeCakeAndSend(cschanstring, countint) {     for i := 1; i <= count; i++ {         cakeName := "Strawberry Cake " + strconv.Itoa(i)         cs <- cakeName //send a strawberry cake     }   }   funcreceiveCakeAndPack(cschanstring) {     for s := range cs {         fmt.Println("Packing received cake: ", s)     } }   funcmain() {     cs := make(chanstring)     gomakeCakeAndSend(cs, 5)     goreceiveCakeAndPack(cs)       //sleep for a while so that the program doesn’t exit immediately     time.Sleep(3 * 1e9) } 
Packingreceivedcake: StrawberryCake 1 Packingreceivedcake: StrawberryCake 2 Packingreceivedcake: StrawberryCake 3 Packingreceivedcake: StrawberryCake 4 Packingreceivedcake: StrawberryCake 5 

Channels and select

golang 的 select 的功能和 select, poll, epoll 相似, 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作。注意到 select 的代码形式和 switch 非常相似, 不过 select 的 case 里的操作语句只能是  IO 操作

package main   import (     "fmt"     "time"     "strconv" )   funcmakeCakeAndSend(cschanstring, flavorstring, countint) {     for i := 1; i <= count; i++ {         cakeName := flavor + " Cake " + strconv.Itoa(i)         cs <- cakeName //send a strawberry cake     }       close(cs) }   funcreceiveCakeAndPack(strbry_cschanstring, choco_cschanstring) {     strbry_closed, choco_closed := false, false       for {         //if both channels are closed then we can stop         if (strbry_closed && choco_closed) { return }         fmt.Println("Waiting for a new cake ...")         select {         case cakeName, strbry_ok := <-strbry_cs:             if (!strbry_ok) {                 strbry_closed = true                 fmt.Println(" ... Strawberry channel closed!")             } else {                 fmt.Println("Received from Strawberry channel.  Now packing", cakeName)             }           case cakeName, choco_ok := <-choco_cs:             if (!choco_ok) {                 choco_closed = true                 fmt.Println(" ... Chocolate channel closed!")             } else {                 fmt.Println("Received from Chocolate channel.  Now packing", cakeName)             }           }       }   }   funcmain() {     strbry_cs := make(chanstring)     choco_cs := make(chanstring)       //two cake makers     gomakeCakeAndSend(choco_cs, "Chocolate", 3)  //make 3 chocolate cakes and send     gomakeCakeAndSend(strbry_cs, "Strawberry", 3)  //make 3 strawberry cakes and send       //one cake receiver and packer     goreceiveCakeAndPack(strbry_cs, choco_cs)  //pack all cakes received on these cake channels       //sleep for a while so that the program doesn’t exit immediately     time.Sleep(2 * 1e9) } 
Waitingfor a new cake ...  ReceivedfromStrawberrychannel. NowpackingStrawberryCake 1  Waitingfor a new cake ...  ReceivedfromChocolatechannel. NowpackingChocolateCake 1  Waitingfor a new cake ...  ReceivedfromChocolatechannel. NowpackingChocolateCake 2  Waitingfor a new cake ...  ReceivedfromStrawberrychannel. NowpackingStrawberryCake 2  Waitingfor a new cake ...  ReceivedfromStrawberrychannel. NowpackingStrawberryCake 3  Waitingfor a new cake ...  ReceivedfromChocolatechannel. NowpackingChocolateCake 3  Waitingfor a new cake ...  ... Strawberrychannelclosed!  Waitingfor a new cake ...  ... Chocolatechannelclosed! 

select 会一直等待等到某个 case 语句完成, 也就是等到成功从 ch1 或者 ch2 中读到数据。 则 select 语句结束

Channels in Go range and select

原文  https://xiequan.info/channels-in-go-range-and-select/
正文到此结束
Loading...