Go語言學習:Channel是什麼?

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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章