Go语言goroutine线程和channel通信

news2024/11/13 6:31:07

Go语言的并发编程通过**goroutinechannel来实现。goroutine是一种轻量级线程,而channel则是Go提供的用于goroutine之间通信**的工具。

1. goroutine的使用

**goroutine**是一种并发执行的函数。使用go关键字可以将一个函数或方法运行在一个新的goroutine中,而不阻塞当前的执行。

示例 1:启动一个简单的goroutine
package main

import (
    "fmt"
    "time"
)

func sayHello() {
    fmt.Println("Hello, Go!")
}

func main() {
    go sayHello() // 启动一个新的 goroutine
    time.Sleep(time.Second) // 主 goroutine 暂停 1 秒,以确保 sayHello 有时间运行
    fmt.Println("Main function done")
}

time.Nanosecond:1纳秒
time.Microsecond:1微秒
time.Millisecond:1毫秒
time.Second:1秒
time.Minute:1分钟
time.Hour:1小时

在这个例子中:

  • go sayHello()在一个新的goroutine中运行。
  • main函数暂停1秒钟,以确保sayHello有足够的时间完成。因为goroutine是异步执行的,所以不等待它结束就会继续执行主程序。
示例 2:在主函数中等待多个goroutine
package main

import (
    "fmt"
    "sync"
)

func printNumber(id int, wg *sync.WaitGroup) {
    defer wg.Done() //使用 defer wg.Done() 确保在 goroutine 结束时调用 Done() 方法,减少 WaitGroup 的计数器。
    fmt.Printf("Goroutine %d is running\n", id)
}

func main() {
    var wg sync.WaitGroup // 使用 WaitGroup 等待所有 goroutine 完成

    for i := 1; i <= 5; i++ {
        wg.Add(1) // 每启动一个 goroutine 就增加计数
        go printNumber(i, &wg)
    }

    wg.Wait() // 等待所有 goroutine 完成
    fmt.Println("All goroutines completed")
}

在这个例子中:

  • sync.WaitGroup用于等待多个goroutine完成。
  • wg.Add(1)在每个goroutine启动时增加计数,defer wg.Done()在每个goroutine结束时减少计数。
  • wg.Wait()阻塞主goroutine,直到所有计数都归零。

2. channel的使用

**channel**是Go中的通信机制,允许多个goroutine间安全地传递数据。channel可以是无缓冲(同步)或有缓冲(异步)的。

示例 3:使用无缓冲的channel

无缓冲的channel要求发送和接收必须同步,即发送和接收操作必须同时准备好,才能完成数据传递。

package main

import (
    "fmt"
)

func sendData(ch chan int) {
    ch <- 10 // 将数据发送到 channel
    fmt.Println("Data sent to channel")
}

func main() {
    ch := make(chan int) // 创建无缓冲 channel

    go sendData(ch) // 启动一个 goroutine 发送数据

    data := <-ch // 从 channel 接收数据
    fmt.Println("Received data:", data)
}

在这个例子中:

  • ch := make(chan int)创建了一个无缓冲的channel
  • sendData函数将数据发送到channel,同时主函数从channel接收数据。这两个操作是同步完成的。
示例 4:使用有缓冲的channel

有缓冲的channel允许在缓冲区满之前发送多个数据,而不需要立即接收。

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 3) // 创建一个缓冲区大小为 3 的 channel

    ch <- 1
    ch <- 2
    ch <- 3 // 可以发送三个数据到 channel 而无需立即接收

    fmt.Println(<-ch) // 从 channel 接收数据:1
    fmt.Println(<-ch) // 从 channel 接收数据:2
    fmt.Println(<-ch) // 从 channel 接收数据:3
}

在这个例子中:

  • make(chan int, 3)创建了一个缓冲区大小为3的channel
  • 可以连续发送三个数据到channel,在缓冲区未满时不需要立即接收。

3. 使用channel同步goroutine

可以使用channel同步多个goroutine的执行,例如在一个goroutine完成任务后通知另一个goroutine继续执行。

示例 5:使用channel同步goroutine
package main

import (
    "fmt"
)

func worker(done chan bool) {
    fmt.Println("Working...")
    done <- true // 完成任务后发送通知
}

func main() {
    done := make(chan bool) // 创建一个无缓冲 channel

    go worker(done) // 启动 worker goroutine

    <-done // 等待 worker goroutine 完成
    fmt.Println("Worker finished")
}

在这个例子中:

  • done是一个无缓冲的channel,用于同步main函数和worker函数。
  • worker完成任务后,会向done发送一个值,main函数会阻塞在<-done直到接收到该值。

4. ✨ select多路复用

select用于同时监听多个channel操作,当多个channel都准备好时,select会随机选择一个执行。

示例 6:select的使用
package main

import (
    "fmt"
    "time"
)

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

    go func() {
        time.Sleep(1 * time.Second)
        ch1 <- "Message from ch1"
    }()

    go func() {
        time.Sleep(2 * time.Second)
        ch2 <- "Message from ch2"
    }()

    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-ch1:
            fmt.Println(msg1)
        case msg2 := <-ch2:
            fmt.Println(msg2)
        }
    }
}

在这个例子中:

  • select语句会等待ch1ch2中的一个准备好,接收到第一个消息后输出结果。
  • 因为ch1会先于ch2发送消息,所以会先打印来自ch1的消息。

5. close关闭channel

关闭channel可以告知接收方不再有数据发送。close关闭channel后不能再次向其中发送数据,否则会引发运行时恐慌。

示例 7:关闭channel
package main

import (
    "fmt"
)

func producer(ch chan int) {
    for i := 0; i < 5; i++ {
        ch <- i
    }
    close(ch) // 关闭 channel
}

func main() {
    ch := make(chan int)
    go producer(ch)

    for num := range ch { // 迭代接收数据,直到 channel 关闭
        fmt.Println(num)
    }
    fmt.Println("Channel closed")
}

在这个例子中:

  • close(ch)用于关闭channel,通知接收方没有更多数据。
  • for num := range ch会自动接收channel中的数据,直到channel关闭。

6. goroutinechannel和并发编程的最佳实践

  • 避免在多个goroutine中同时写入同一个channel:多个goroutine写入同一个channel时,需要确保并发安全,通常需要借助sync.Mutexsync.WaitGroup来控制。
  • 不要对已关闭的channel写入数据:向已关闭的channel写入数据会导致运行时恐慌,因此确保只关闭一次channel,并且关闭后不再写入。
  • 利用select处理多通道场景select可以实现多路复用,有效处理多个channel的同时监听需求。
  • 考虑使用带缓冲的channel来提升性能:对于一些高吞吐量场景,有缓冲的channel可以减少阻塞,提高效率。

总结

  • goroutine:是Go语言中并发执行的轻量级线程,通过go关键字启动。
  • channel:是goroutine之间进行通信和同步的工具,分为无缓冲和有缓冲两种。
  • select:用于监听多个channel操作,方便处理多路复用。
  • close:关闭channel后可以通知接收方不再有数据发送。

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

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

相关文章

思维,CF 1735D - Meta-set

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1735D - Meta-set 二、解题报告 1、思路分析 考虑一个五元组<a, b, c…

C#的6种常用集合类

一.先来说说数组的不足&#xff08;也可以说集合与数组的区别&#xff09;&#xff1a; 1.数组是固定大小的&#xff0c;不能伸缩。虽然System.Array.Resize这个泛型方法可以重置数组大小&#xff0c;但是该方法是重新创建新设置大小的数组&#xff0c;用的是旧数组的元素初始…

深度学习-神经网络基础-激活函数与参数初始化(weight, bias)

一. 神经网络介绍 神经网络概念 神经元构建 神经网络 人工神经网络是一种模仿生物神经网络结构和功能的计算模型, 由神经元构成 将神经元串联起来 -> 神经网络 输入层: 数据 输出层: 目标(加权和) 隐藏层: 加权和 激活 全连接 第N层的每个神经元和第N-1层的所有神经元…

SpringBoot框架在资产管理中的应用

3系统分析 3.1可行性分析 通过对本企业资产管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本企业资产管理系统采用Spring Boot框架&#xff0c;JAVA作…

【C#】选课程序增加、删除统计学时

文章目录 【例6-2】编写选课程序。利用利用列表框和组合框增加和删除相关课程&#xff0c;并统计学时数1. 表6-2 属性设置2. 设计窗体及页面3. 代码实现4. 运行效果 【例6-2】编写选课程序。利用利用列表框和组合框增加和删除相关课程&#xff0c;并统计学时数 分析&#xff1…

uniapp—android原生插件开发(1环境准备)

本篇文章从实战角度出发&#xff0c;将UniApp集成新大陆PDA设备RFID的全过程分为四部曲&#xff0c;涵盖环境搭建、插件开发、AAR打包、项目引入和功能调试。通过这份教程&#xff0c;轻松应对安卓原生插件开发与打包需求&#xff01; 项目背景&#xff1a; UniApp集成新大陆P…

ProtoBuf实战之网络版通讯录

目录 网络版通讯录需求 实现网络版通讯录 搭建服务端客户端 协议约定 客户端菜单功能 服务端代码 Protobuf 还常用于 通讯协议、服务端数据交换 的场景&#xff0c;接下来&#xff0c;我们将实现一个网络版本的通讯录&#xff0c;模拟实现客户端与服务端的交互&#xff0…

动态规划理论基础和习题【力扣】【算法学习day.26】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

Sqoop学习

目录 一、Soop简介 二、Sqoop的安装 1. 上传压缩包到/opt/install目录下 2.解压 3.修改文件名 4.拷贝sqoop-1.4.7.bin__hadoop-2.6.0目录下的sqoop-1.4.7.jar包到/opt/soft/sqoop147目录下 5.拷贝sqoop-1.4.7.bin__hadoop-2.6.0/lib目录下该jar包到sqoop/lib目录下 6.复…

关于随身wifi,看了再决定要不要买!2024年最受欢迎的随身wifi品牌推荐!

话费、流量费缴纳起来肉疼&#xff0c;毕竟不是每个月都有很大需求&#xff0c;主打一个该省省该花花。特别是短租人群、在校学生、出差或旅游的人群、追求高性价比的人群&#xff0c;随身Wifi特别实用&#xff0c;出门当WiFi&#xff0c;在家当宽带&#xff0c;两不耽误&#…

[vulnhub] DarkHole: 1

https://www.vulnhub.com/entry/darkhole-1,724/ 端口扫描主机发现 探测存活主机&#xff0c;184是靶机 nmap -sP 192.168.75.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-08 09:59 CST Nmap scan report for 192.168.75.1 Host is up (0.00027s latency). MA…

iPhone 微信传大文件到QQ

问题 解决方法 在微信里打开要拷贝的文件 选择“...” 选择“用其他应用打开” 长按QQ 选择“拷贝到App”&#xff08;有些版本是“在App中打开”&#xff09;

【学习笔记】网络设备(华为交换机)基础知识 11 —— 信息中心 ② 配置案例

提示&#xff1a;学习华为交换机信息中心配置案例&#xff0c;包含配置输出Log信息 &#xff08; 输出到Log缓冲区、控制台、日志文件、终端 &#xff09;、配置输出Trap信息 &#xff08; 输出到Trap缓冲区、控制台、日志文件、终端 &#xff09;、 配置输出Debug信息 &#x…

电脑管家实时监控软件下载 | 六款知名又实用的电脑监控软件推荐!(珍藏篇)

在当今的商业环境&#xff0c;企业对于员工在工作期间的行为监控需求越来越强烈。 尤其是在网络化和信息化程度不断提高的今天&#xff0c;电脑管家实时监控软件是企业管理员工工作行为、提高工作效率、防止信息泄露的重要工具。 本文&#xff0c;将为您推荐六款知名又实用的电…

PICO+Unity MR空间网格

官方链接&#xff1a;空间网格 | PICO 开发者平台 注意&#xff1a;该功能只能打包成APK在PICO 4 Ultra上真机运行&#xff0c;无法通过串流或PICO developer center在PC上运行。使用之前要开启视频透视。 在 Inspector 窗口中的 PXR_Manager (Script) 面板上&#xff0c;勾选…

Spring Boot中集成MyBatis操作数据库详细教程

目录 前言1. 项目依赖配置1.1 引入MyBatis和数据库驱动依赖1.2 数据源配置 2. 创建数据库映射实体类3. 创建Mapper层接口4. 创建Service层4.1 定义Service接口4.2 实现Service接口 5. 创建Controller层6. 运行和测试项目6.1 启动项目6.2 测试接口 7. 总结 前言 在Java开发中&a…

DirectShow过滤器开发-写AVI视频文件过滤器

下载本过滤器DLL 本过滤器将视频流和音频流写入AVI视频文件。 过滤器信息 过滤器名称&#xff1a;写AVI 过滤器GUID&#xff1a;{2EF49957-37DF-4356-A2A0-ECBC52D1984B} DLL注册函数名&#xff1a;DllRegisterServer 删除注册函数名&#xff1a;DllUnregisterServer 过滤器有…

使用 API 和离线库查询 IP 地址方法详解

目录 一、IP 地址查询能获取哪些信息1.地理位置信息2.网络信息3.网络类型 二、IP 地址查询方法&#xff0c;附代码1.在线查询 IP 地址方法2.使用 API 进行 IP 地址查询3.使用离线库进行 IP 地址查询 互联网监管部门要求公开 IP 归属地&#xff0c;引起了很大热度&#xff0c;但…

机器学习在时间序列预测中的应用与实现——以电力负荷预测为例(附代码)

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 随着数据采集技术的发展&#xff0c;时间序列数据在各个领域中的应用越来越广泛。时间序列预测旨在基于过去的时间数据来…

语音识别ic赋能烤箱,离线对话操控,引领智能厨房新体验

一、智能烤箱产品的行业背景 随着科技的飞速发展&#xff0c;智能家居已经成为现代家庭的新宠。智能烤箱作为智能家居的重要组成部分&#xff0c;正逐渐从高端市场走向普通家庭。消费者对于烤箱的需求不再仅仅局限于基本的烘焙功能&#xff0c;而是更加注重其智能化、便捷化和…