Golang 菜鳥(niǎo)教程

Golang 控制語(yǔ)句

Golang 函數(shù) & 方法

Golang 結(jié)構(gòu)體

Golang 切片 & 數(shù)組

Golang 字符串(String)

Golang 指針

Golang 接口

Golang 并發(fā)

Golang 異常(Error)

Golang 其他雜項(xiàng)

Go 語(yǔ)言通道(Channel)

在Go語(yǔ)言中,通道是goroutine與另一個(gè)goroutine通信的媒介,并且這種通信是無(wú)鎖的。換句話說(shuō),通道是一種技術(shù),它允許一個(gè)goroutine將數(shù)據(jù)發(fā)送到另一個(gè)goroutine。默認(rèn)情況下,通道是雙向的,這意味著goroutine可以通過(guò)同一通道發(fā)送或接收數(shù)據(jù),如下圖所示:

創(chuàng)建通道

在Go語(yǔ)言中,使用chan關(guān)鍵字創(chuàng)建通道,并且該通道只能傳輸相同類型的數(shù)據(jù),不允許從同一通道傳輸不同類型的數(shù)據(jù)。

語(yǔ)法:

var Channel_name chan Type

您還可以使用簡(jiǎn)寫(xiě)聲明通過(guò)make()函數(shù)創(chuàng)建通道。

語(yǔ)法:

channel_name:= make(chan Type)
package main

import "fmt"

func main() {

    //使用var關(guān)鍵字創(chuàng)建通道
    var mychannel chan int
    fmt.Println("channel的值: ", mychannel)
    fmt.Printf("channel的類型: %T ", mychannel)

    // 使用 make() 函數(shù)創(chuàng)建通道
    mychannel1 := make(chan int)
    fmt.Println("\nchannel1的值:", mychannel1)
    fmt.Printf("channel1的類型: %T ", mychannel1)
}

輸出:

channel的值:  <nil>
channel的類型: chan int
channel1的值: 0xc0000160c0
channel1的類型: chan int

從通道發(fā)送和接收數(shù)據(jù)

在Go語(yǔ)言中,通道工作有兩個(gè)主要的操作,一個(gè)是發(fā)送,另一個(gè)是接收,這兩個(gè)操作統(tǒng)稱為通信。<-運(yùn)算符的方向表示是接收數(shù)據(jù)還是發(fā)送數(shù)據(jù)。在通道中,默認(rèn)情況下,發(fā)送和接收操作塊直到另一端沒(méi)有數(shù)據(jù)為止。它允許goroutine在沒(méi)有顯式鎖或條件變量的情況下彼此同步。

  1. 發(fā)送操作:發(fā)送操作用于在通道的幫助下將數(shù)據(jù)從一個(gè)goroutine發(fā)送到另一個(gè)goroutine。像int,float64和bool之類的值可以安全且容易地通過(guò)通道發(fā)送,因?yàn)樗鼈兪潜粡?fù)制的,因此不存在意外并發(fā)訪問(wèn)相同值的風(fēng)險(xiǎn)。同樣,字符串也是安全的,因?yàn)樗鼈兪遣豢勺兊?。但是,通過(guò)通道發(fā)送指針或引用(例如切片,map集合等)并不安全,因?yàn)橹羔樆蛞玫闹悼赡軙?huì)通過(guò)同時(shí)發(fā)送goroutine或接收goroutine更改,并且結(jié)果無(wú)法預(yù)測(cè)。因此,在通道中使用指針或引用時(shí),必須確保它們一次只能由一個(gè)goroutine訪問(wèn)。

    Mychannel <- element

    上面的語(yǔ)句表明數(shù)據(jù)(element)在<-運(yùn)算符的幫助下發(fā)送到通道(Mychannel)。

  2. 接收操作:接收操作用于接收發(fā)送操作方發(fā)送的數(shù)據(jù)。

    element := <-Mychannel

    上面的語(yǔ)句表明該元素從channel(Mychannel)接收數(shù)據(jù)。如果接收到的語(yǔ)句的結(jié)果不可用(不需要使用),則也是有效的語(yǔ)句。您還可以編寫(xiě)如下的receive語(yǔ)句:

    <-Mychannel
package main 
  
import "fmt"
  
func myfunc(ch chan int) { 
  
    fmt.Println(234 + <-ch) 
} 
func main() { 
    fmt.Println("主方法開(kāi)始") 
    //創(chuàng)建通道l 
    ch := make(chan int) 
  
    go myfunc(ch) 
    ch <- 23 
    fmt.Println("主方法結(jié)束") 
}

輸出:

主方法開(kāi)始
257
主方法結(jié)束

關(guān)閉通道

您也可以在close()函數(shù)的幫助下關(guān)閉通道。這是一個(gè)內(nèi)置函數(shù),并設(shè)置一個(gè)標(biāo)識(shí),表示不再有任何值將發(fā)送到該通道。

語(yǔ)法:

close()

您也可以使用for范圍循環(huán)關(guān)閉通道。在這里,接收器goroutine可以借助給定的語(yǔ)法檢查通道是打開(kāi)還是關(guān)閉:

ele, ok:= <- Mychannel

在此,如果ok的值為true,則表示通道已打開(kāi),因此可以執(zhí)行讀取操作。并且,如果的值為false,則表示該通道已關(guān)閉,因此將不執(zhí)行讀取操作。

//Go程序說(shuō)明如何
//關(guān)閉使用的通道
//range循環(huán)和關(guān)閉函數(shù)
package main

import "fmt"

func myfun(mychnl chan string) {

    for v := 0; v < 4; v++ {
        mychnl <- "nhooo"
    }
    close(mychnl)
}

func main() {

    //創(chuàng)建通道
    c := make(chan string)

    // 使用 Goroutine
    go myfun(c)

    //當(dāng)ok的值為為true時(shí),表示通道已打開(kāi),可以發(fā)送或接收數(shù)據(jù)
    //當(dāng)ok的值設(shè)置為false時(shí),表示通道已關(guān)閉
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println("通道關(guān)閉 ", ok)
            break
        }
        fmt.Println("通道打開(kāi) ", res, ok)
    }
}

輸出:

通道打開(kāi)  nhooo true
通道打開(kāi)  nhooo true
通道打開(kāi)  nhooo true
通道打開(kāi)  nhooo true
通道關(guān)閉  false

重要注意事項(xiàng)

  • 阻止發(fā)送和接收:在通道中,當(dāng)數(shù)據(jù)發(fā)送到通道時(shí),控制在發(fā)送語(yǔ)句中被阻塞,直到其他goroutine從該通道讀取數(shù)據(jù)。類似地,當(dāng)通道從goroutine接收數(shù)據(jù)時(shí),read語(yǔ)句塊直到另一條goroutine語(yǔ)句。

  • 零值通道:通道的零值為nil。

  • 通道中的For循環(huán): for循環(huán)可以遍歷通道上發(fā)送的順序值,直到關(guān)閉為止。

    語(yǔ)法:

    for item := range Chnl { 
         // 語(yǔ)句..
    }
    package main 
    import "fmt"
      
    func main() { 
      
        // 使用 make() 函數(shù)創(chuàng)建通道
        mychnl := make(chan string) 
      
        // 匿名 goroutine 
        go func() { 
            mychnl <- "GFG"
            mychnl <- "gfg"
            mychnl <- "Geeks"
            mychnl <- "nhooo"
            close(mychnl) 
        }() 
      
        //使用for循環(huán)
        for res := range mychnl { 
            fmt.Println(res) 
        } 
    }

    輸出:

    GFG
    gfg
    Geeks
    nhooo
  • 通道的長(zhǎng)度:在通道中,您可以使用len()函數(shù)找到通道的長(zhǎng)度。在此,長(zhǎng)度表示在通道緩沖區(qū)中排隊(duì)的值的數(shù)量。

    package main 
      
    import "fmt"
    
    func main() { 
      
        // 使用 make() 函數(shù)創(chuàng)建通道 
        mychnl := make(chan string, 4) 
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "nhooo"
    
        // 使用  len() 函數(shù)查找通道的長(zhǎng)度 
        fmt.Println("channel長(zhǎng)度為: ", len(mychnl)) 
    }

    輸出:

    channel長(zhǎng)度為:  4
  • 通道的容量:在通道中,您可以使用cap()函數(shù)找到通道的容量。在此,容量表示緩沖區(qū)的大小。

    package main
    
    import "fmt"
    
    func main() {
    
        // 使用 make() 函數(shù)創(chuàng)建通道
        mychnl := make(chan string, 4)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "nhooo"
    
        // 使用  cap() 函數(shù)查找通道的容量
        fmt.Println("channel容量為: ", cap(mychnl))
    }

    輸出:

    channel容量為:  5
  • Channel中的Select和case語(yǔ)句:在go語(yǔ)言中,select語(yǔ)句就像沒(méi)有任何輸入?yún)?shù)的switch語(yǔ)句。在通道中使用select語(yǔ)句從case塊提供的多個(gè)操作中執(zhí)行單個(gè)操作。


丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清