首页 > 其他分享 >go教程6

go教程6

时间:2024-01-23 10:48:46浏览次数:35  
标签:Received 教程 int chan number 信道 go true

关闭信道和使用 for range 遍历信道

数据发送方可以关闭信道,通知接收方这个信道不再有数据发送过来。

当从信道接收数据时,接收方可以多用一个变量来检查信道是否已经关闭。

v, ok := <- ch

上面的语句里,如果成功接收信道所发送的数据,那么 ok 等于 true。而如果 ok 等于 false,说明我们试图读取一个关闭的通道。从关闭的信道读取到的值会是该信道类型的零值。例如,当信道是一个 int 类型的信道时,那么从关闭的信道读取的值将会是 0

package main
 
import (  
    "fmt"
)
 
func producer(chnl chan int) {  
    for i := 0; i < 10; i++ {
        chnl <- i
    }
    close(chnl)
}
func main() {  
    ch := make(chan int)
    go producer(ch)
    for {
        v, ok := <-ch
        if ok == false {
            break
        }
        fmt.Println("Received ", v, ok)
    }
}

在线运行程序

在上述的程序中,producer 协程会从 0 到 9 写入信道 chn1,然后关闭该信道。主函数有一个无限的 for 循环(第 16 行),使用变量 ok(第 18 行)检查信道是否已经关闭。如果 ok 等于 false,说明信道已经关闭,于是退出 for 循环。如果 ok 等于 true,会打印出接收到的值和 ok 的值。

Received  0 true  
Received  1 true  
Received  2 true  
Received  3 true  
Received  4 true  
Received  5 true  
Received  6 true  
Received  7 true  
Received  8 true  
Received  9 true

for range 循环用于在一个信道关闭之前,从信道接收数据。

接下来我们使用 for range 循环重写上面的代码。

package main
 
import (  
    "fmt"
)
 
func producer(chnl chan int) {  
    for i := 0; i < 10; i++ {
        chnl <- i
    }
    close(chnl)
}
func main() {  
    ch := make(chan int)
    go producer(ch)
    for v := range ch {
        fmt.Println("Received ",v)
    }
}

在线运行程序

在第 16 行,for range 循环从信道 ch 接收数据,直到该信道关闭。一旦关闭了 ch,循环会自动结束,如果不关闭,for range循环会一直把线程卡死。该程序会输出:

Received  0  
Received  1  
Received  2  
Received  3  
Received  4  
Received  5  
Received  6  
Received  7  
Received  8  
Received  9

我们可以使用 for range 循环,重写信道的另一个示例这一节里面的代码,提高代码的可重用性。

如果你仔细观察这段代码,会发现获得一个数里的每位数的代码在 calcSquares 和 calcCubes 两个函数内重复了。我们将把这段代码抽离出来,放在一个单独的函数里,然后并发地调用它。

package main
 
import (  
    "fmt"
)
 
func digits(number int, dchnl chan int) {  
    for number != 0 {
        digit := number % 10
        dchnl <- digit
        number /= 10
    }
    close(dchnl)
}
func calcSquares(number int, squareop chan int) {  
    sum := 0
    dch := make(chan int)
    go digits(number, dch)
    for digit := range dch {
        sum += digit * digit
    }
    squareop <- sum
}
 
func calcCubes(number int, cubeop chan int) {  
    sum := 0
    dch := make(chan int)
    go digits(number, dch)
    for digit := range dch {
        sum += digit * digit * digit
    }
    cubeop <- sum
}
 
func main() {  
    number := 589
    sqrch := make(chan int)
    cubech := make(chan int)
    go calcSquares(number, sqrch)
    go calcCubes(number, cubech)
    squares, cubes := <-sqrch, <-cubech
    fmt.Println("Final output", squares+cubes)
}

在线运行程序

上述程序里的 digits 函数,包含了获取一个数的每位数的逻辑,并且 calcSquares 和 calcCubes 两个函数并发地调用了 digits。当计算完数字里面的每一位数时,第 13 行就会关闭信道。calcSquares 和 calcCubes 两个协程使用 for range 循环分别监听了它们的信道,直到该信道关闭。程序的其他地方不变,该程序同样会输出:

Final output 1536
本教程的内容到此结束

标签:Received,教程,int,chan,number,信道,go,true
From: https://www.cnblogs.com/gongxianjin/p/17981800

相关文章

  • go教程8
    1.    合取代继承      Go不支持继承,但它支持组合(Composition)。组合一般定义为“合并在一起”。汽车就是一个关于组合的例子:一辆汽车由车轮、引擎和其他各种部件组合在一起。通过嵌套结构体进行组合在Go中,通过在结构体内嵌套结构体,可以实现组合。组合的典型例......
  • go教程10
    1.    自定义错误在上一教程里,我们学习了Go中的错误是如何表示的,并学习了如何处理标准库里的错误。我们还学习了从标准库的错误中提取更多的信息。在本教程中,我们会学习如何创建我们自己的自定义错误,并在我们创建的函数和包中使用它。我们会使用与标准库中相同的技术,来提......
  • go教程9
    什么是defer?defer 语句的用途是:含有 defer 语句的函数,会在该函数将要返回之前,调用另一个函数。这个定义可能看起来很复杂,我们通过一个示例就很容易明白了。示例packagemain import(     "fmt") funcfinished(){     fmt.Println("Finishedfindi......
  • go教程11
    1.    Panic和recover什么是panic?在Go语言中,程序中一般是使用错误来处理异常情况。对于程序中出现的大部分异常情况,错误就已经够用了。但在有些情况,当程序发生异常时,无法继续运行。在这种情况下,我们会使用 panic 来终止程序。当函数发生panic时,它会终止运行,在执行......
  • go教程12
    1.    读取文件文件读取是所有编程语言中最常见的操作之一。本教程我们会学习如何使用Go读取文件。本教程分为如下小节。将整个文件读取到内存使用绝对文件路径使用命令行标记来传递文件路径将文件绑定在二进制文件中分块读取文件逐行读取文件将整个文件读取......
  • go教程
    这是我们 Golang系列教程的第一个教程。1.    GO介绍与安装Golang是什么     Go亦称为Golang(译注:按照RobPike说法,语言叫做Go,Golang只是官方网站的网址),是由谷歌开发的一个开源的编译型的静态语言。     Golang的主要关注点是使得高可用性和可扩展......
  • 使用Go进行HTTP客户端认证
    在Go语言中,HTTP客户端认证可以通过net/http包来实现。下面是一个简单的示例,展示如何使用Go进行HTTP客户端认证。首先,确保你已经安装了Go语言环境,并设置好了相关的环境变量。Go语言中的HTTP客户端认证主要涉及到设置请求头中的认证信息。以下是一个简单的示例代码,展示了如何使用Go发......
  • 在Go中处理HTTP重定向
    在Go语言中处理HTTP重定向是一个常见的任务,特别是在开发Web应用程序或与Web服务进行交互时。HTTP重定向是一种服务器端的行为,它告诉客户端请求的资源已移动到新的位置,并提供了新的位置信息。Go语言的net/http包提供了处理HTTP请求和响应的工具,包括重定向的处理。以下是一个示例,展示......
  • 使用Go编写HTTP中间件
    在Go语言中,HTTP中间件是一种处理HTTP请求和响应的函数,它可以拦截到请求并对其进行处理,然后再将请求传递给下一个中间件或目标处理程序。HTTP中间件在Web应用程序中非常常见,它提供了一种机制来执行各种任务,例如身份验证、授权、日志记录和错误处理等。下面是一个使用Go编写HTTP中间......
  • 使用Go进行HTTP性能优化
    Go语言,也被称为Golang,是一种高效且强大的编程语言,特别适合构建高性能的Web应用程序。在处理HTTP请求时,通过一些优化技巧,可以显著提高应用程序的性能。以下是一些使用Go进行HTTP性能优化的方法:1. 并发处理:Go语言内置的并发原语,如goroutine和channel,使得并发编程变得简单而高效。你......