开放的编程资料库

当前位置:我爱分享网 > Go教程 > 正文

如何在 Golang 中使用通道

在本文中,我们展示了如何在Golang中使用通道。

$ go version
go version go1.18.1 linux/amd64

我们使用Go版本1.18。

Goroutine是一个轻量级的执行线程。它是一个与其他正在运行的代码同时运行的函数。

通道用于goroutine之间的通信。

渠道功能和运营商

在本节中,我们介绍了与通道相关的函数和运算符。

c := make(chan int)

频道是使用make函数和chan关键字创建的。频道被赋予一种类型。

<-运算符用于读取通道和写入通道。

c <- v

此行将值写入通道。

<- c

此行从通道读取值。

close(c)

使用close函数关闭通道。

for e := range(c) {
    fmt.Println(e)
}

我们可以使用range迭代通道中的值。

len(c)

len函数返回已经成功发送到通道但还没有被取出的元素个数。

单向通道

默认情况下,通道是双向的。它们均可用于发送和接收数据。

rc chan<- int

将箭头运算符放在chan关键字的右侧,我们创建了一个只接收通道。

wc <-chan int

将箭头运算符放在chan关键字的左侧,我们创建了一个只发送通道。

Go通道简单示例

下面是一个使用通道的简单示例。

package main

import "fmt"

func main() {

    c := make(chan string)

    go func() {

        c <- "an old falcon"
    }()

    msg := <-c

    fmt.Println(msg)
}

在程序中,我们有两个协程。一个是使用go关键字创建的;main函数也是一个goroutine。

c := make(chan string)

我们创建一个字符串类型的通道。

go func() {

    c <- "an old falcon"
}()

在匿名goroutine中,我们向通道发送字符串消息。

msg := <-c

在主goroutine中,我们从通道中读取值。

$ go run main.go
an old falcon

去通道死锁

当代码在使用通道时被阻塞时会发生通道死锁。当我们尝试从打开的空通道中读取或尝试写入打开的已满通道时,通道被阻塞。

package main

import "fmt"

func main() {

    c := make(chan string)

    c <- "an old falcon"
    msg := <-c

    fmt.Println(msg)
}

这个程序以死锁结束。

c <- "an old falcon"

我们将值写入通道。channel阻塞等待,直到清空。因此,从channel中读取并清空的那条线没有到达。这种情况导致死锁。

$ go run main.go
fatal error: all goroutines are asleep - deadlock!
...

去通道范围

我们可以使用range关键字来遍历发送到通道的数据。

package main

import (
    "fmt"
    "time"
)

func main() {

    c := make(chan string)
    go hello("Martin", c)

    for msg := range c {

        fmt.Println(msg)
    }
}

func hello(name string, c chan string) {

    for i := 0; i < 5; i++ {

        msg := fmt.Sprintf("Hello %s!", name)
        c <- msg
        time.Sleep(time.Millisecond * 500)
    }

    close(c)
}

在程序中,我们向一个频道发送了五条消息。

go hello("Martin", c)

一个hellogoroutine是用go创建的。我们将通道作为参数传递。

for msg := range c {

    fmt.Println(msg)
}

使用range关键字,我们遍历消息并将它们打印到控制台。

func hello(name string, c chan string) {

    for i := 0; i < 5; i++ {

        msg := fmt.Sprintf("Hello %s!", name)
        c <- msg
        time.Sleep(time.Millisecond * 500)
    }

    close(c)
}

hello函数中,我们创建了五个消息并通过通道将它们发送到maingoroutine。当goroutine完成时,我们用close关闭通道。

$ go run main.go
Hello Martin!
Hello Martin!
Hello Martin!
Hello Martin!
Hello Martin!

单向通道示例

在下面的例子中,我们使用单向通道。

package main

import "fmt"

func main() {

    c1 := make(chan int)
    c2 := make(chan int)

    go power(c2, c1)
    go power(c2, c1)
    go power(c2, c1)

    c2 <- 2
    fmt.Println(<-c1)

    c2 <- 4
    fmt.Println(<-c1)

    c2 <- 5
    fmt.Println(<-c1)

}

func power(wc <-chan int, rc chan<- int) {

    num := <-wc
    res := num * num
    rc <- res
}

在程序中,我们有一个power函数,它接受一个只写的wc通道和一个只读的rc通道。

$ go run main.go
4
16
25

在本文中,我们使用了Go通道。

列出所有Go教程。

未经允许不得转载:我爱分享网 » 如何在 Golang 中使用通道

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏