[go]channel(介绍3)

juejin.cn/post/743935...

参考网址, 感谢大佬分享

实例

go 复制代码
var ChannelName chan *AAA       //AAA是一个结构体
// 有缓冲的channel, 当通道还有空的时候,就可以一直往里写数据, 如果没空, 就堵塞
ChannelName = make(chan *AAA, 4096) 


func InitChannel() {
    go FUCN_1()

}

func FUCN_1() {
     defer func() {
        err := recover()
        if err != nil {
           glog.Error(err)
        }
     }()

    for {
      request := <-ChannelName
      val, err := json.Marshal(request.val)
      if err == nil {
           db.TraceRedis.Set(request.Key, string(val), time.Hour*24)
      }
    }
}

Go语言中的 Channel 是一种特殊的类型,它提供了一种在两个或多个协程间传递数据的方式。

缓冲区

go 复制代码
ch := make(chan Type, bufferSize)
// 其中,`Type` 是 channel 中传递的元素类型,`bufferSize` 是缓冲区的大小。

在 Go 语言中,channel 是一种用于在不同的 goroutine 之间进行通信的类型化管道。

channel 可以是有缓冲区的(buffered)或无缓冲区的(unbuffered)。

缓冲区的大小决定了 channel 可以同时存储多少个元素而不必阻塞发送方或接收方。

缓冲区大小的选择

选择缓冲区大小通常取决于具体的应用场景和需求:

  1. 无缓冲区(bufferSize == 0

    • 无缓冲区的 channel 意味着发送操作会阻塞,直到另一方准备好接收数据。
    • 适用于需要严格同步的场景,比如信号量、生产者-消费者模型中的同步点。
  2. 有缓冲区

    • 有缓冲区的 channel 允许在缓冲区未满时发送操作不阻塞,或在缓冲区未空时接收操作不阻塞。
    • 缓冲区大小的选择依赖于发送和接收操作的频率和模式。
    • 缓冲区太大会导致内存浪费,太小则可能导致频繁的阻塞和性能问题。

例子

go 复制代码
package main
 
import (
	"fmt"
	"time"
)
 
func producer(ch chan int, count int) {
	for i := 0; i < count; i++ {
		ch <- i
		fmt.Printf("Produced: %d\n", i)
		time.Sleep(time.Millisecond * 100) // 模拟生产时间
	}
	close(ch)
}
 
func consumer(ch chan int) {
	for num := range ch {
		fmt.Printf("Consumed: %d\n", num)
		time.Sleep(time.Millisecond * 150) // 模拟消费时间
	}
}
 
func main() {
	bufferSize := 5
	ch := make(chan int, bufferSize)
 
	go producer(ch, 10)
	go consumer(ch)
 
	time.Sleep(time.Second * 2) // 确保所有操作完成

}

创建

在 Go 语言中,创建一个 channel 非常简单,我们可以使用 make 函数创建一个无缓冲和有缓冲的 channel, 两者的区别在于是否可以存储值。

go 复制代码
ch := make(chan int)     // 创建一个无缓冲 channel
ch := make(chan int, 10) // 创建一个缓冲区位 10 的 channel

读写

(1)阻塞

go 复制代码
ch <- 10  // 写入

val := <-ch // 读取,接受值
<-ch // 读取,不关心值
//当我们往无缓冲的 channel 中写入值时,需要有另外一个协程在读,不然此时写入的协程就会陷于阻塞状态; 
//当我们往一个带有缓冲区的的 channel 中写入值时,如果缓冲区没满时,则可以正常写入,当缓冲区满时,则也会陷入阻塞的状态。

(2)非阻塞

go 复制代码
select {
    case val := <-ch:
            ...
    default:
            ...
}

select {
    case ch <- val:
            ...
    default:
            ...
}
// 尝试从 channel 中读取数据时,使用`select`语句加上`default`分支可实现非阻塞接收。
// 如果 channel 为空,会执行`default`分支的代码。

// 尝试往 channel 中写入数据时,使用`select`语句加上`default`分支可实现非阻塞写入。
// 如果 channel 已满,会执行`default`分支的代码。

3关闭

scss 复制代码
close(ch)

//当你不需要再向 channel 中写入值时,则可以使用 close 函数关闭 channel。
//此时,你还是可以从 channel 中读取值。

//同时,在从 channel 中读取值时,我们还可以根据 channel 的返回值判断 channel 中是否已经为空, 当接受的第二个值为 false 时,则表示 channel 此时已经为空,val 会返回元素类型的零值。
相关推荐
梦帮科技5 小时前
GRAVIS v4.0:基于Web的极速套利架构设计与实时数据流实现
前端·人工智能·rust·自动化·区块链·智能合约·数字货币
爱勇宝6 小时前
办公资料反复修改、补传、交接混乱,我做了个桌面工具来解决这件事
前端·后端·程序员
微信开发api-视频号协议7 小时前
企业微信外部群开发自动化实践过程
java·前端·微信·自动化·企业微信·ipad
甲维斯7 小时前
Fable5:20美金的顶级设计师!
前端·人工智能
kyriewen7 小时前
我同时用了 Claude Code、Cursor 和 Codex,说说三个工具的真实差距——2026 年选错工具比不用 AI 更浪费时间
前端·ai编程·claude
Jackson__7 小时前
为了拯救我的腰椎和颈椎,我做了款浏览器插件!
前端·javascript·开源
闲猫8 小时前
Python FastAPI + SQLAlchemy 入门教程:从零搭建你的第一个 Web 应用
前端·python·fastapi
林小帅8 小时前
NestJS v11 + Prisma v7 ESM 迁移配置解析
前端·javascript·后端
IT_陈寒8 小时前
React的setState竟然不是立刻生效的,害我调试半天
前端·人工智能·后端
简简单单就是我_hehe8 小时前
前端埋点日志解决方案:完整 User-Agent 解析工具实现,爬虫识别、设备品牌、操作系统、浏览器版本全解析(附完整源码)
前端·爬虫