牛骨文教育服务平台(让学习变的简单)

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
",p1)

    persionChan <- p1

    p1.Address.district = "shijingshan"
    fmt.Printf("P2 (2): %v
",p1)

    p1_copy := <-persionChan
    fmt.Printf("p1_copy: %v
",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)
", 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.