Go语言struct{}类型的channel

本文深入探讨了Go语言中特殊struct类型channel的应用,包括任务等待、同时启动多个任务及停止事件等场景,展示了如何利用channel进行高效并发控制。

简介

在Go语言中,有一种特殊的struct{}类型的channel,它不能被写入任何数据,只有通过close()函数进行关闭操作,才能进行输出操作。。struct类型的channel不占用任何内存!!!
定义:

var sig = make(chan struct{})

解除方式:

package main

func main() {
	var sig = make(chan struct{})
	close(sig)   // 必须进行close,才能执行<-sig,否则是死锁
	<-sig
}

应用

等待某任务的结束:

done := make(chan struct{})
go func() { 
  doLongRunningThing()
  close(done)
}()
// do some other bits
// wait for that long running thing to finish
<-done
// do more things

有很多方式可以完成这种操作,这是其中一个。。

同一时刻启动多个任务:

start := make(chan struct{})
for i := 0; i < 10000; i++ {
  go func() {
    <-start // wait for the start channel to be closed
    doWork(i) // do something
 }()
}
// at this point, all goroutines are ready to go - we just need to 
// tell them to start by closing the start channel
close(start)

这是真正意义上的同一时刻,不再是并发,是并行。。。

停止某事件:

loop:
for {
  select {
  case m := <-email:
    sendEmail(m)
  case <-stop: // triggered when the stop channel is closed
    break loop // exit
  }
}

一旦关闭了stop,整个循环就会终止。这在Golang的官方包io.pipe中有应用

参考博客

https://medium.com/@matryer/golang-advent-calendar-day-two-starting-and-stopping-things-with-a-signal-channel-f5048161018

<think>我们正在讨论Go语言channelstruct的使用。根据用户需求,我们需要提供关于channelstruct的教程或学习文章。结合之前的引用内容,我们可以知道channel的基本使用(声明、初始化、发送和接收),以及struct的定义和使用。由于用户同时提到了channelstruct,我们可以考虑如何将两者结合使用,例如在channel中传递struct类型的数据。回答结构:1.介绍channelstruct的基本概念。2.分别讲解struct的定义和channel的创建。3.展示如何在channel中使用struct(即通过channel传递struct类型的值)。4.给出一个综合示例,展示如何使用channelstruct进行并发编程。5.提供相关学习资源或进一步阅读建议。注意:引用内容中已经包含了channel的一些基本知识,我们可以适当引用。根据引用[1]和[2]:channel需要指定类型,可以使用make创建,有缓冲和无缓冲两种。struct是自定义类型,可以包含多个字段。我们按照以下步骤组织回答:第一步:struct的定义第二步:channel的创建(针对struct类型)第三步:在goroutine中使用channel传递struct第四步:示例代码同时,我们需要生成相关问题。</think>### Go语言channelstruct的使用教程 #### 一、struct基础 structGo语言中的复合数据类型,用于封装多个字段: ```go type Person struct { Name string Age int Addr string } // 初始化方式 p1 := Person{"Alice", 30, "Beijing"} p2 := Person{Name: "Bob", Age: 25} ``` #### 二、channel基础 channelGo的并发原语,用于goroutine间通信: 1. **创建channel** 引用[1]:使用`make()`创建,需指定元素类型: ```go // 无缓冲channel ch1 := make(chan Person) // 有缓冲channel(容量10) ch2 := make(chan Person, 10) ``` 2. **发送与接收数据** 引用[2]:通过`<-`操作符通信: ```go // 发送数据到channel ch1 <- Person{"Tom", 28, "Shanghai"} // 从channel接收数据 p := <-ch1 ``` #### 三、结合使用channelstruct ##### 典型场景:goroutine间传递结构化数据 ```go package main type Task struct { ID int Data string Status chan string // channel作为struct字段 } func worker(taskChan chan Task) { for task := range taskChan { // 处理任务 result := process(task.Data) // 通过struct内的channel返回状态 task.Status <- fmt.Sprintf("Task %d: %s", task.ID, result) } } func main() { taskChan := make(chan Task, 5) // 启动worker go worker(taskChan) // 创建带状态channel的Task statusCh := make(chan string) task := Task{ID: 1, Data: "file1", Status: statusCh} // 发送任务 taskChan <- task // 接收状态 fmt.Println(<-statusCh) // 输出: Task 1: processed_file1 } ``` ##### 关键应用场景: 1. **工作池模式** 引用[3]:使用buffered channel实现任务队列: ```go tasks := make(chan Task, 100) for i := 0; i < 10; i++ { go worker(tasks) // 10个worker并发处理 } ``` 2. **事件广播** 通过关闭channel通知所有接收者: ```go type Server struct { stopChan chan struct{} } func (s *Server) Stop() { close(s.stopChan) // 广播停止信号 } ``` 3. **互斥控制** 利用channel实现信号量: ```go type Resource struct { sem chan struct{} } func (r *Resource) Use() { r.sem <- struct{}{} // 获取令牌 defer func() { <-r.sem }() // 释放令牌 // 安全操作... } ``` #### 四、注意事项 1. **channel零值** 引用[2]:未初始化的channel默认为`nil`,发送/接收会永久阻塞 2. **死锁预防** 无缓冲channel需配对发送/接收操作 3. **资源释放** 不再使用的channel应显式关闭避免内存泄漏 #### 学习资源推荐 1. [官方并发指南](https://golang.org/doc/effective_go#concurrency) 2. [Go by Example: Channels](https://gobyexample.com/channels) 3. [深入解析Channel实现原理](https://draveness.me/golang/concurrency/golang-channel.html)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值