Go语言学习:Channel是什么?

最后更新于:2022-04-01 11:59:16

# Channel是什么 > 在Go语言中,Channel即指通道类型。有时也用它来直接指代可以传递某种类型的值的通道。 ### 类型表示法 - chan T - 关键字chan代表了通道类型的关键字,T则代表了该通道类型的元素类型。 - 例如:type IntChan chan int 别名类型IntChan代表了元素类型为int的通道类型。我们可以直接声明一个chan int类型的变量:var IntChan chan int,在被初始化后,变量IntChan就可以被用来传递int类型的元素值了。 - chan<- T - 只能被用来发送值, <-表示发送操作符 - <-chan T - 接收通道值, <-表示接收操作符 ### 值表示法 ### 属性和基本操作 - 基于通道的通讯是在多个Goroutine之间进行同步的重要手段。而针对通道的操作本身也是同步的。 - 在同一时刻,仅有一个Goroutine能向一个通道发送元素值 - 同时也仅有一个Goroutine能从它那里接收元素值。 - 通道相当于一个FIFO先进先出的消息队列。 - 通道中的元素值都具有原子性。它们是不可被分割的。通道中的每一个元素都只可能被某一个Goroutine接收。已被接收的元素值会立刻被从通道中删除。 ### 初始化通道 > make(chan int, 10) ~ 表达式初始化了一个通道类型的值。传递给make函数的第一个参数表明此值的具体类型是元素类型为int的通道类型,而第二个参数则指该值在同一时刻最多可以容纳10个元素值。 ~~~ package main import ( "fmt" ) type Person struct { Name string Age uint8 Address Addr } type Addr struct{ city string district string } func main(){ persionChan := make(chan Person,1) p1 := Person{"Harry",32,Addr{"Shanxi","Xian"}} fmt.Printf("P1 (1): %v\n",p1) persionChan <- p1 p1.Address.district = "shijingshan" fmt.Printf("P2 (2): %v\n",p1) p1_copy := <-persionChan fmt.Printf("p1_copy: %v\n",p1_copy) } ~~~ ~~~ #go test.go 运行结果 P1 (1): {Harry 32 {Shanxi Xian}} P2 (2): {Harry 32 {Shanxi shijingshan}} p1_copy: {Harry 32 {Shanxi Xian}} ~~~ > 通道中的元素值丝毫没有受到外界的影响。这说明了,在发送过程中进行的元素值属于完全复制。这也保证了我们使用通道传递的值的不变性。 ### 单向通道 单向channel只能用于发送或者接收数据 > var ch1 chan int // ch1是一个正常的channel,不是单向的 var ch2 chan<- float64// ch2是单向channel,只用于写float64数据 var ch3 <-chan int // ch3是单向channel,只用于读取int数据 channel是一个原生类型,因此不仅 支持被传递,还支持类型转换。只有在介绍了单向channel的概念后,读者才会明白类型转换对于 channel的意义:就是在单向channel和双向channel之间进行转换。 **示例如下:** ch4 := make(chan int) ch5 := <-chan int(ch4) // ch5就是一个单向的读取channel ch6 := chan<- int(ch4) // ch6 是一个单向的写入channel 基于ch4,我们通过类型转换初始化了两个单向channel:单向读的ch5和单向写的ch6。 从设计的角度考虑,所有的代码应该都遵循“最小权限原则” 简单单向channel案例: ~~~ func Parse(ch <-chan int) { for value := range ch { fmt.Println("Parsing value", value) } } ~~~ ### 关闭通道 > close(strChan) 我们应该先明确一点:无论怎么样都不应该在接收端关闭通道。因为在那里我们无法判断发送端是否还会向该通道发送元素值。 如何判断一个channel是否已经被关 闭?我们可以在读取的时候使用多重返回值的方式: str, ok := strChan,只需要判断第二个bool返回值即可,false表示strChan已经被关闭。 ~~~ package main import ( "fmt" "time" ) func main(){ ch := make(chan int, 5) sign := make(chan int, 2) go func() { for i :=0;i<5;i++ { ch <- i time.Sleep(1 * time.Second) } close(ch) fmt.Println("The channel is closed.") sign <- 0 }() go func() { for { e, ok := <-ch fmt.Printf("%d (%v)\n", e,ok) if !ok { break } time.Sleep(2 * time.Second) } fmt.Println("Done.") sign <- 1 }() <- sign <- sign } ~~~ > 运行结果: 0 (true) 1 (true) 2 (true) The channel is closed. 3 (true) 4 (true) 0 (false) Done. 运行时系统并没有在通道ch被关闭之后立即把false作为相应接收操作的第二个结果,而是等到接收端把已在通道中的所有元素值都接收到之后才这样做。这确保了在发送端关闭通道的安全性。 ### 完整示例 ~~~ package main import ( "fmt" //"time" ) type Person struct { Name string Age uint8 Address Addr } type Addr struct{ city string district string } type PersonHandler interface { Batch(origs <-chan Person) <-chan Person Handle(orig *Person) } //类型声明 type PersonHandlerImpl struct{} func(handler PersonHandlerImpl) Batch(origs <-chan Person) <-chan Person{ //初始化通道dests dests := make(chan Person, 100) go func(){ //需要被更改的人员信息会通过origs单向通道传递进来,那么我们就应该不断的试图从该通道中接收它们。 for p := range origs { //变更人员信息 handler.Handle(&p) //把人员信息发送给通道dests dests <- p } fmt.Println("All the information has been handled.") //关闭通道dests close(dests) }() return dests } func(handler PersonHandlerImpl) Handle(orig *Person){ //处理人员信息 if orig.Address.district == "Haidian"{ orig.Address.district = "ShiJingshan" } } func getPersonHandler() PersonHandler{ return PersonHandlerImpl{} } var personTotal = 200 var persons []Person = make([]Person, personTotal) var personCount int func init(){ //初始化人员信息 for i := 0;i<personTotal;i++{ name := fmt.Sprintf("%s%d","P",i) p := Person{name,24,Addr{"Beijing","Haidian"}} persons[i] = p } } func main(){ handler := getPersonHandler() //初始化通道origs origs := make(chan Person, 100) //启用G2以处理人员信息 dests := handler.Batch(origs) //启用G3以获取人员信息 fecthPerson(origs) //启用G4以存储人员信息 sign := savePerson(dests) <- sign } //接受一个参数 是只允许写入origs通道 func fecthPerson(origs chan<- Person){ go func(){ for _,p := range persons{ origs <- p } fmt.Println("All the information has been fetched.") close(origs) }() } //接受一个参数 是只允许读取dest通道 除非直接强制转换 要么你只能从channel中读取数据 func savePerson(dest <-chan Person) <-chan byte { sign := make(chan byte,1) go func(){ for{ p, ok := <-dest if !ok { fmt.Println("All the information has been saved.") sign <- 0 break } savePerson1(p) } }() return sign } func savePerson1(p Person) bool { fmt.Println(p) return true } ~~~ 运行后结果: All the information has been fetched. {P0 24 {Beijing ShiJingshan}} {P1 24 {Beijing ShiJingshan}} {P2 24 {Beijing ShiJingshan}} {P3 24 {Beijing ShiJingshan}} {P4 24 {Beijing ShiJingshan}} {P5 24 {Beijing ShiJingshan}} {P6 24 {Beijing ShiJingshan}} {P7 24 {Beijing ShiJingshan}} {P8 24 {Beijing ShiJingshan}} {P9 24 {Beijing ShiJingshan}} {P10 24 {Beijing ShiJingshan}} {P11 24 {Beijing ShiJingshan}} {P12 24 {Beijing ShiJingshan}} {P13 24 {Beijing ShiJingshan}} {P14 24 {Beijing ShiJingshan}} {P15 24 {Beijing ShiJingshan}} {P16 24 {Beijing ShiJingshan}} {P17 24 {Beijing ShiJingshan}} {P18 24 {Beijing ShiJingshan}} {P19 24 {Beijing ShiJingshan}} {P20 24 {Beijing ShiJingshan}} {P21 24 {Beijing ShiJingshan}} {P22 24 {Beijing ShiJingshan}} {P23 24 {Beijing ShiJingshan}} {P24 24 {Beijing ShiJingshan}} {P25 24 {Beijing ShiJingshan}} {P26 24 {Beijing ShiJingshan}} {P27 24 {Beijing ShiJingshan}} {P28 24 {Beijing ShiJingshan}} {P29 24 {Beijing ShiJingshan}} {P30 24 {Beijing ShiJingshan}} {P31 24 {Beijing ShiJingshan}} {P32 24 {Beijing ShiJingshan}} {P33 24 {Beijing ShiJingshan}} {P34 24 {Beijing ShiJingshan}} {P35 24 {Beijing ShiJingshan}} {P36 24 {Beijing ShiJingshan}} {P37 24 {Beijing ShiJingshan}} {P38 24 {Beijing ShiJingshan}} {P39 24 {Beijing ShiJingshan}} {P40 24 {Beijing ShiJingshan}} {P41 24 {Beijing ShiJingshan}} {P42 24 {Beijing ShiJingshan}} {P43 24 {Beijing ShiJingshan}} {P44 24 {Beijing ShiJingshan}} {P45 24 {Beijing ShiJingshan}} {P46 24 {Beijing ShiJingshan}} {P47 24 {Beijing ShiJingshan}} {P48 24 {Beijing ShiJingshan}} {P49 24 {Beijing ShiJingshan}} {P50 24 {Beijing ShiJingshan}} {P51 24 {Beijing ShiJingshan}} {P52 24 {Beijing ShiJingshan}} {P53 24 {Beijing ShiJingshan}} {P54 24 {Beijing ShiJingshan}} {P55 24 {Beijing ShiJingshan}} {P56 24 {Beijing ShiJingshan}} {P57 24 {Beijing ShiJingshan}} {P58 24 {Beijing ShiJingshan}} {P59 24 {Beijing ShiJingshan}} {P60 24 {Beijing ShiJingshan}} {P61 24 {Beijing ShiJingshan}} {P62 24 {Beijing ShiJingshan}} {P63 24 {Beijing ShiJingshan}} {P64 24 {Beijing ShiJingshan}} {P65 24 {Beijing ShiJingshan}} {P66 24 {Beijing ShiJingshan}} {P67 24 {Beijing ShiJingshan}} {P68 24 {Beijing ShiJingshan}} {P69 24 {Beijing ShiJingshan}} {P70 24 {Beijing ShiJingshan}} {P71 24 {Beijing ShiJingshan}} {P72 24 {Beijing ShiJingshan}} {P73 24 {Beijing ShiJingshan}} {P74 24 {Beijing ShiJingshan}} {P75 24 {Beijing ShiJingshan}} {P76 24 {Beijing ShiJingshan}} {P77 24 {Beijing ShiJingshan}} {P78 24 {Beijing ShiJingshan}} {P79 24 {Beijing ShiJingshan}} {P80 24 {Beijing ShiJingshan}} {P81 24 {Beijing ShiJingshan}} {P82 24 {Beijing ShiJingshan}} {P83 24 {Beijing ShiJingshan}} {P84 24 {Beijing ShiJingshan}} {P85 24 {Beijing ShiJingshan}} {P86 24 {Beijing ShiJingshan}} {P87 24 {Beijing ShiJingshan}} {P88 24 {Beijing ShiJingshan}} {P89 24 {Beijing ShiJingshan}} {P90 24 {Beijing ShiJingshan}} {P91 24 {Beijing ShiJingshan}} {P92 24 {Beijing ShiJingshan}} {P93 24 {Beijing ShiJingshan}} {P94 24 {Beijing ShiJingshan}} {P95 24 {Beijing ShiJingshan}} {P96 24 {Beijing ShiJingshan}} {P97 24 {Beijing ShiJingshan}} {P98 24 {Beijing ShiJingshan}} {P99 24 {Beijing ShiJingshan}} All the information has been handled. {P100 24 {Beijing ShiJingshan}} {P101 24 {Beijing ShiJingshan}} {P102 24 {Beijing ShiJingshan}} {P103 24 {Beijing ShiJingshan}} {P104 24 {Beijing ShiJingshan}} {P105 24 {Beijing ShiJingshan}} {P106 24 {Beijing ShiJingshan}} {P107 24 {Beijing ShiJingshan}} {P108 24 {Beijing ShiJingshan}} {P109 24 {Beijing ShiJingshan}} {P110 24 {Beijing ShiJingshan}} {P111 24 {Beijing ShiJingshan}} {P112 24 {Beijing ShiJingshan}} {P113 24 {Beijing ShiJingshan}} {P114 24 {Beijing ShiJingshan}} {P115 24 {Beijing ShiJingshan}} {P116 24 {Beijing ShiJingshan}} {P117 24 {Beijing ShiJingshan}} {P118 24 {Beijing ShiJingshan}} {P119 24 {Beijing ShiJingshan}} {P120 24 {Beijing ShiJingshan}} {P121 24 {Beijing ShiJingshan}} {P122 24 {Beijing ShiJingshan}} {P123 24 {Beijing ShiJingshan}} {P124 24 {Beijing ShiJingshan}} {P125 24 {Beijing ShiJingshan}} {P126 24 {Beijing ShiJingshan}} {P127 24 {Beijing ShiJingshan}} {P128 24 {Beijing ShiJingshan}} {P129 24 {Beijing ShiJingshan}} {P130 24 {Beijing ShiJingshan}} {P131 24 {Beijing ShiJingshan}} {P132 24 {Beijing ShiJingshan}} {P133 24 {Beijing ShiJingshan}} {P134 24 {Beijing ShiJingshan}} {P135 24 {Beijing ShiJingshan}} {P136 24 {Beijing ShiJingshan}} {P137 24 {Beijing ShiJingshan}} {P138 24 {Beijing ShiJingshan}} {P139 24 {Beijing ShiJingshan}} {P140 24 {Beijing ShiJingshan}} {P141 24 {Beijing ShiJingshan}} {P142 24 {Beijing ShiJingshan}} {P143 24 {Beijing ShiJingshan}} {P144 24 {Beijing ShiJingshan}} {P145 24 {Beijing ShiJingshan}} {P146 24 {Beijing ShiJingshan}} {P147 24 {Beijing ShiJingshan}} {P148 24 {Beijing ShiJingshan}} {P149 24 {Beijing ShiJingshan}} {P150 24 {Beijing ShiJingshan}} {P151 24 {Beijing ShiJingshan}} {P152 24 {Beijing ShiJingshan}} {P153 24 {Beijing ShiJingshan}} {P154 24 {Beijing ShiJingshan}} {P155 24 {Beijing ShiJingshan}} {P156 24 {Beijing ShiJingshan}} {P157 24 {Beijing ShiJingshan}} {P158 24 {Beijing ShiJingshan}} {P159 24 {Beijing ShiJingshan}} {P160 24 {Beijing ShiJingshan}} {P161 24 {Beijing ShiJingshan}} {P162 24 {Beijing ShiJingshan}} {P163 24 {Beijing ShiJingshan}} {P164 24 {Beijing ShiJingshan}} {P165 24 {Beijing ShiJingshan}} {P166 24 {Beijing ShiJingshan}} {P167 24 {Beijing ShiJingshan}} {P168 24 {Beijing ShiJingshan}} {P169 24 {Beijing ShiJingshan}} {P170 24 {Beijing ShiJingshan}} {P171 24 {Beijing ShiJingshan}} {P172 24 {Beijing ShiJingshan}} {P173 24 {Beijing ShiJingshan}} {P174 24 {Beijing ShiJingshan}} {P175 24 {Beijing ShiJingshan}} {P176 24 {Beijing ShiJingshan}} {P177 24 {Beijing ShiJingshan}} {P178 24 {Beijing ShiJingshan}} {P179 24 {Beijing ShiJingshan}} {P180 24 {Beijing ShiJingshan}} {P181 24 {Beijing ShiJingshan}} {P182 24 {Beijing ShiJingshan}} {P183 24 {Beijing ShiJingshan}} {P184 24 {Beijing ShiJingshan}} {P185 24 {Beijing ShiJingshan}} {P186 24 {Beijing ShiJingshan}} {P187 24 {Beijing ShiJingshan}} {P188 24 {Beijing ShiJingshan}} {P189 24 {Beijing ShiJingshan}} {P190 24 {Beijing ShiJingshan}} {P191 24 {Beijing ShiJingshan}} {P192 24 {Beijing ShiJingshan}} {P193 24 {Beijing ShiJingshan}} {P194 24 {Beijing ShiJingshan}} {P195 24 {Beijing ShiJingshan}} {P196 24 {Beijing ShiJingshan}} {P197 24 {Beijing ShiJingshan}} {P198 24 {Beijing ShiJingshan}} {P199 24 {Beijing ShiJingshan}} All the information has been saved.
';