Go基础编程 - 09 - 通道(channel)

news2024/10/6 20:37:02

通道(channel)

    • 1. 声明
    • 2. channel的操作
    • 3. 无缓冲通道
    • 4. 有缓冲通道
    • 5. 如何优雅的从通道循环取值
    • 6. 单向通道
    • 7. 异常总结

上一篇:结构体


Go语言的并发模式:不要通过共享内存来通信,而应该通过通信来共享内存

Go语言的通道(channel)是一种特殊类型,遵循先进先出(FIFO)的原则,声明channel时需要指定元素类型。

channel是一种通信机制,用于在不同的goroutine之间传递数据。

1. 声明

channel 是一种引用类型,空值是 nil。声明后的 channel 变量是未初始化的,需要使用make函数初始化。

  • 声明channel:var 变量 chan 元素类型
  • 创建channel:ch := make(chan 元素类型, 缓冲大小)

元素类型:通道中存放的数据类型。

package main

import "fmt"

func main() {
    // 声明
    var ch chan int
    fmt.Println(ch) // <nil>
    // 初始化
    ch = make(chan int, 3)
}

2. channel的操作

  • 操作符:<-
  • 发送(send):ch <- 元素值
  • 接收(receive):元素值 := <-ch
  • 关闭(close):close(ch)
package main

import "fmt"

func main() {
    ch := make(chan int, 3)

    ch <- 1 // 把 1 发送到 ch
    ch <- 2
    ch <- 3
    //ch <- 4  // 超出缓冲大小:fatal error: all goroutines are asleep - deadlock!

    i := <-ch  // 从 ch 接收一个值,并赋值给 i
    fmt.Println(i)

    <-ch       // 从 ch 接收一个值,并丢弃
    <-ch
    
    j, ok := <-ch   // 通道未关闭且无元素值,则堵塞:fatal error: all goroutines are asleep - deadlock!
    fmt.Printf("i = %d, j = %d, ok = %v\n", i, j, ok)

    ch <- 4
    close(ch)   // 关闭通道 ch
    //ch <- 5     // 通道关闭后,不可再发送:panic: send on closed channel

    k, ok := <-ch   // 通道关闭后,若通道内还有值,接收依然可以接收通道中的元素。
    fmt.Printf("k = %d, ok = %v\n", k, ok)

    m, ok := <-ch   // 通道关闭且无元值,得到对应类型的零值。ok为false说明通道已没有元素值可取了
    fmt.Printf("k = %d, ok = %v\n", m, ok)
}

关闭后的通道具有以下特点:

  1. 通道关闭后,发送操作引发 panic

  2. 通道关闭后,若通道内还有值,接收操作依然可以接收通道中的元素。

  3. 通道关闭且没有值,接收操作会得到对应类型的零值。接收表达式可接收两个值,第一个值为接收到的元素值,第二个值为bool类型,如果为false,则说明通道已没有元素值可取了,且通道已关闭。

    注:若通道未关闭且无元素值,接收操作堵塞。

  4. 关闭一个已关闭的通道,会引发panic。

3. 无缓冲通道

又称为堵塞通道。无论send还是receive一开始执行就会被堵塞,直到配对的操作也开始执行,才会继续传递。

同步方式传递数据:使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。

package main

import "fmt"

func main() {
    ch := make(chan int)
    go func(c chan int) {
        ret := <-c
        fmt.Println("接收成功", ret)
    }(ch)

    ch <- 10
    fmt.Println("发送成功")
}

无缓冲通道

4. 有缓冲通道

只要通道的容量大于零,那么该通道就是有缓冲的通道,通道的容量表示通道中能存放元素的数量。

获取通道内元素数量:len(ch)

获取通道的容量:cap(ch)

func main() {
    ch := make(chan int, 10) // 创建一个容量为1的有缓冲区通道
    ch <- 10
    fmt.Println("发送成功")
}

异步方式传递数据
有缓冲通道

5. 如何优雅的从通道循环取值

通过channel发送有限数据时,可以通过close函数关闭通道来告诉通道接收值的goroutine停止等待。

package main

import "fmt"

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)

    // goroutine
    go func() {
        for i := 0; i < 100; i++ {
            ch1 <- i
        }
        close(ch1)
    }()

    go func() {
        for {
            i, ok := <-ch1  
            if !ok {    // ok为false,表面通道已关闭且没有元素值可取了
                break
            }
            ch2 <- i * i
        }
        close(ch2)
    }()

    // 主goroutine
    for i := range ch2 { // 通道关闭后会退出for range循环
        fmt.Println(i)
    }
}

6. 单向通道

有的时候我们会将通道作为参数在多个任务函数间传递,很多时候我们在不同的任务函数中使用通道都会对其进行限制,比如限制通道在函数中只能发送或只能接收。

Go语言中提供了单向通道来处理这种情况。例如,我们把上面的例子改造如下:

package main

import "fmt"

func counter(out chan<- int) { // 限制out仅为发送通道
    for i := 0; i < 100; i++ {
        out <- i
    }
    close(out)
}

func squarer(out chan<- int, in <-chan int) {
    for i := range in {
        out <- i * i
    }
    close(out)
}

func printer(in <-chan int) {   // in限制为接收通道
    for i := range in {
        fmt.Println(i)
    }
}

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go counter(ch1) // GO语言会自动把双向通道转换为函数所需要的单向通道
    go squarer(ch2, ch1)
    printer(ch2)
}

7. 异常总结

异常总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1831426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring框架永远滴神之SpringAI玩转大模型

文章目录 一、SpringAI简介1.什么是SpringAI2.SpringAI支持的大模型类型&#xff08;1&#xff09;聊天模型&#xff08;2&#xff09;文本到图像模型&#xff08;3&#xff09;转录&#xff08;音频到文本&#xff09;模型&#xff08;4&#xff09;嵌入模型&#xff08;5&…

报错:C1189#error: The <experimental/filesystem> header providing 解决方案

今天开发过程中&#xff0c;需要使用文件系统experimental/filesystem&#xff0c;报错C1189#error: The &#xff1c;experimental/filesystem&#xff1e; header providing &#xff0c;通过以下解决方案&#xff0c;成功运行程序。 目录 一、打开项目下的属性 二、选择C/…

离散数学-代数系统证明题归类

什么是独异点&#xff1f; 运算 在B上封闭&#xff0c;运算 可结合&#xff0c;且存在幺元。 学会合理套用题目公式结合律 零元&#xff1f; 群中不可能有零元 几个结论要熟记&#xff1a; 1.当群的阶为1时&#xff0c;它的唯一元素视作幺元e 2.若群的阶大于1时&#xff0c;…

PV180R1K1T1NMMC派克通轴传动结构柱塞泵

PV180R1K1T1NMMC派克通轴传动结构柱塞泵 派克柱塞泵的结构组成部分&#xff1a;柱塞、手把、斜盘、压盘、滑履、泵体、配油盘、传送轴。其优点如下&#xff1a; 1、结构紧凑耐用&#xff0c;具有灵活的安装接口 2、安静的工作 3、效率高 4、降低功耗和减少发热 5、具有“…

视角概述( Perspective 业务分析篇)

背景 在业务分析工作中使用透视图来提供对特定于计划上下文的任务和技术的关注。大多数提案可能涉及一个或多个视角。视角主要包括&#xff1a; •敏捷•商业智能•信息技术•商业架构&#xff0c;以及业务流程管理。这些视角并不代表业务分析实践的所有可能视角。 任何给定…

SpringMvc—域对象共享数据和视图

一、向request域创建对象 先创建首页&#xff1a; 在testController这个类中&#xff1a; package com.pon.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; Controller public class test…

【UE5.1】制作自己的载具

目录 前言 效果 步骤 一、制作载具模型 二、载具设置 三、控制载具 前言 在前面我们通过UE4完成了载具的制作&#xff0c;下面我们介绍一下如何通过UE5制作载具。 效果 步骤 一、制作载具模型 制作方法同【UE4 制作自己的载具】1-使用3dsmax制作载具 二、载具设置 …

高考杂志高考杂志社高考编辑部2024年第14期目录

高考论坛 新高考背景下优化高中数学教学方法探究 韩玉新; 3-5 基于高考评价体系的高中历史大单元复习模式建构 钱敏杰; 6-8 新高考背景下高中语文课堂优化作业设计策略 吴丽容; 9-11《高考》投稿&#xff1a;cn7kantougao163.com 新高考视域下高中地理课堂促进…

别太小看“静态免杀“

0x01 简述 免杀总体来说可分为两种&#xff0c;静态免杀/动态免杀。往往来说&#xff0c;我们更注重于在内部代码层面实现一些免杀技巧&#xff0c;但在有些时候&#xff0c;动态免杀静态免杀以"打组合拳"的方式效果往往会更出人所料。 当我们的程序生成后&#xf…

高考志愿填报和未来的职业规划

高考成绩出来那一刻&#xff0c;我们就站在了人生的岔路口上&#xff0c;面临这不同的选择&#xff0c;走不同的路线、过不同的生活...... 除了成绩会决定一个人的未来走向之外&#xff0c;报考的专业和学校影响也是终身。高考志愿填报和未来职业规划应该息息相关&#xff0c;…

python图像处理库-PIL(Pillow)

PIL库全称为Python Imaging Library&#xff0c;即Python图像处理库&#xff0c;是一个在Python中用于处理图像的非常流行的库。 一、PIL介绍 这个库提供了广泛的文件格式支持、高效的内部表示以及相当强大的图像处理功能。 核心图像库旨在快速访问存储在几种基本像素格式中的数…

【C++】模板进阶(特化)

&#x1f308;个人主页&#xff1a;秦jh_-CSDN博客&#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12575764.html?spm1001.2014.3001.5482 目录 非类型模板参数 数组越界检查 按需实例化 模板的特化 函数模板特化 类模板特化 全特化 ​…

【网络编程开发】17.“自动云同步“项目实践

17."自动云同步"项目实践 文章目录 17."自动云同步"项目实践项目简介功能需求需求分析实现步骤 1.实现TCP通信server.c 服务端tcp.hclient.c 客户端 函数封装tcp.ctcp.hserver.cclient.c编译运行 2.实现文件传输sever.cclient.ctcp.ctcp.hMakeifle编译运行…

死锁预防之银行家算法

死锁预防之银行家算法 第一章 概述 Dijkstra提出了一种能够避免死锁的调度算法,称为银行家算法。 它的模型基于一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,每个客户都有一个贷款额度,银行家知道不可能所有客户同时都需要最大贷款额,所以他只保留一定单位…

wps 二维数据转转一维度数据

HSTACK(TOCOL(C2:H2&A3:A8),TOCOL(B3:B8&C1:H1),TOCOL(C3:H8))

------构造类型数据—结构体---- + ----函数-----

构造类型数据——结构体 1&#xff09;结构体的基本概念 结构体&#xff08;struct&#xff09;是C语言&#xff08;以及其他一些编程语言&#xff09;中用于将不同类型的数据组合成一个单一类型的方式。这种数据类型允许你将多个变量&#xff08;可能是不同类型&#xff09;…

iconfont的使用(超简单)

iconfont的使用&#xff08;超简单&#xff09; 1、iconfont 是什么&#xff1f;2、使用2.1、新建项目2.2、搜图标 添加 至项目中2.3、下载iconfont的包文件![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/91a0a07cd4b74798b7fb333dddca7724.png)2.4、画一个文件夹…

基于Python的花卉识别分类系统【W9】

简介&#xff1a; 基于Python的花卉识别分类系统利用深度学习和计算机视觉技术&#xff0c;能够准确识别和分类各种花卉&#xff0c;如玫瑰、郁金香和向日葵等。这种系统不仅有助于植物学研究和园艺管理&#xff0c;还在生态保护、智能农业和市场销售等领域展现广泛应用前景。随…

springboot原理篇-bean管理

springboot原理篇-bean管理&#xff08;二&#xff09; 我们今天主要学习IOC容器中Bean的其他使用细节&#xff0c;主要学习以下三方面&#xff1a; 如何从IOC容器中手动的获取到bean对象bean的作用域配置管理第三方的bean对象 一、获取Bean 了解即可&#xff0c;默认情况下…