Go 语言通道(Channel)

在Go语言中,通道是goroutine与另一个goroutine通信的媒介,并且这种通信是无锁的。换句话说,通道是一种技术,它允许一个goroutine将数据发送到另一个goroutine。默认情况下,通道是双向的,这意味着goroutine可以通过同一通道发送或接收数据,如下图所示:

创建通道

在Go语言中,使用chan关键字创建通道,并且该通道只能传输相同类型的数据,不允许从同一通道传输不同类型的数据。

语法:

var Channel_name chan Type

您还可以使用简写声明通过make()函数创建通道。

语法:

channel_name:= make(chan Type)
package main

import "fmt"

func main() {

    //使用var关键字创建通道
    var mychannel chan int
    fmt.Println("channel的值: ", mychannel)
    fmt.Printf("channel的类型: %T ", mychannel)

    // 使用 make() 函数创建通道
    mychannel1 := make(chan int)
    fmt.Println("\nchannel1的值:", mychannel1)
    fmt.Printf("channel1的类型: %T ", mychannel1)
}

输出:

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

从通道发送和接收数据

在Go语言中,通道工作有两个主要的操作,一个是发送,另一个是接收,这两个操作统称为通信。<-运算符的方向表示是接收数据还是发送数据。在通道中,默认情况下,发送和接收操作块直到另一端没有数据为止。它允许goroutine在没有显式锁或条件变量的情况下彼此同步。

Mychannel <- element
element := <-Mychannel
<-Mychannel
package main 
  
import "fmt"
  
func myfunc(ch chan int) { 
  
    fmt.Println(234 + <-ch) 
} 
func main() { 
    fmt.Println("主方法开始") 
    //创建通道l 
    ch := make(chan int) 
  
    go myfunc(ch) 
    ch <- 23 
    fmt.Println("主方法结束") 
}

输出:

主方法开始
257
主方法结束

关闭通道

您也可以在close()函数的帮助下关闭通道。这是一个内置函数,并设置一个标识,表示不再有任何值将发送到该通道。

语法:

close()

您也可以使用for范围循环关闭通道。在这里,接收器goroutine可以借助给定的语法检查通道是打开还是关闭:

ele, ok:= <- Mychannel

在此,如果ok的值为true,则表示通道已打开,因此可以执行读取操作。并且,如果的值为false,则表示该通道已关闭,因此将不执行读取操作。

//Go程序说明如何
//关闭使用的通道
//range循环和关闭函数
package main

import "fmt"

func myfun(mychnl chan string) {

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

func main() {

    //创建通道
    c := make(chan string)

    // 使用 Goroutine
    go myfun(c)

    //当ok的值为为true时,表示通道已打开,可以发送或接收数据
    //当ok的值设置为false时,表示通道已关闭
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println("通道关闭 ", ok)
            break
        }
        fmt.Println("通道打开 ", res, ok)
    }
}

输出:

通道打开  nhooo true
通道打开  nhooo true
通道打开  nhooo true
通道打开  nhooo true
通道关闭  false

重要注意事项

for item := range Chnl { 
     // 语句..
}
package main 
import "fmt"
  
func main() { 
  
    // 使用 make() 函数创建通道
    mychnl := make(chan string) 
  
    // 匿名 goroutine 
    go func() { 
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "nhooo"
        close(mychnl) 
    }() 
  
    //使用for循环
    for res := range mychnl { 
        fmt.Println(res) 
    } 
}
GFG
gfg
Geeks
nhooo
package main 
  
import "fmt"

func main() { 
  
    // 使用 make() 函数创建通道 
    mychnl := make(chan string, 4) 
    mychnl <- "GFG"
    mychnl <- "gfg"
    mychnl <- "Geeks"
    mychnl <- "nhooo"

    // 使用  len() 函数查找通道的长度 
    fmt.Println("channel长度为: ", len(mychnl)) 
}
channel长度为:  4
package main

import "fmt"

func main() {

    // 使用 make() 函数创建通道
    mychnl := make(chan string, 4)
    mychnl <- "GFG"
    mychnl <- "gfg"
    mychnl <- "Geeks"
    mychnl <- "nhooo"

    // 使用  cap() 函数查找通道的容量
    fmt.Println("channel容量为: ", cap(mychnl))
}
channel容量为:  5