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.