go并发基础(2) | 豆包MarsCode AI刷题

39 阅读3分钟

func CalSquare() {
	src := make(chan int)
	dest := make(chan int, 3)
	go func() {
		defer close(src)
		for i := 0; i < 10; i++ {
			src <- i
		}
	}()
	go func() {
		defer close(dest)
		for i := range src {
			dest <- i * i
		}
	}()
	for i := range dest {
		println(i)
	
}
  1. 包声明

    go package concurrence 这一行声明了代码所在的包为concurrence

  2. 函数定义

    go

    func CalSquare() {

        //...

    }

    这是一个名为CalSquare的函数,它没有参数也没有返回值。

  3. 创建通道

    go src := make(chan int) dest := make(chan int, 3) 这里创建了两个通道:srcdestsrc是一个无缓冲通道,用于发送整数;dest是一个有缓冲通道,容量为3,用于接收平方数。

  4. 启动生成器协程: go go func() {     defer close(src)     for i := 0; i < 10; i++ {         src <- i     } }()

    这个匿名函数创建了一个协程,它向src通道发送从0到9的整数,然后关闭src通道。

  5. 启动计算协程

    go go func() {     defer close(dest)     for i := range src {        dest <- i * i     } }() 这个匿名函数也创建了一个协程,它从src通道接收整数,计算平方,并将结果发送到dest通道,然后关闭dest通道。

  6. 主协程接收并打印结果

    go for i := range dest {     println(i) }

    主协程从dest通道接收平方数,并打印出来。

总结来说,这个程序通过两个协程并发地生成整数和计算平方,然后在主协程中打印结果。这种并发模型允许程序高效地处理多个任务,提高了程序的性能和响应速度。

Go 语言的并发模型基于 goroutines 和 channels,这是一种非常高效且易于使用的并发方式。下面将补充一些 Go 并发的进阶概念和技巧:

  1. Goroutines: Goroutine 是 Go 语言中的轻量级线程,由 Go 运行时管理。它们非常便宜,可以轻松创建成千上万个。Goroutines 通过 go 关键字启动。
  2. Channels: Channels 是 Go 语言中用于在 goroutines 之间安全传递数据的管道。它们可以是无缓冲的或有缓冲的。无缓冲的 channels 同步发送和接收操作,而有缓冲的 channels 允许一定数量的值在没有接收者的情况下发送。
  3. Select 语句: select 语句用于同时等待多个 channels 的操作。这在你需要从多个 channels 中接收数据或者向多个 channels 发送数据时非常有用。
  4. Default Case in Select: 在 select 语句中,如果没有其他 case 可以运行,可以选择执行一个默认 case。
  5. sync 包: Go 标准库中的 sync 包提供了互斥锁(Mutex)、读写锁(RWMutex)和条件变量(Cond),用于更细粒度的同步控制。
  6. WaitGroup: sync.WaitGroup 用于等待一组 goroutines 完成。它通过 Add 方法增加计数器,每个 goroutine 完成时调用 Done 方法减少计数器,主 goroutine 通过 Wait 方法等待计数器归零。
  7. Once: sync.Once 用于确保初始化或其他互斥执行的代码块只被执行一次。
  8. 原子操作: Go 语言提供了原子操作,如 atomic.AddInt32,这些操作不需要使用互斥锁就可以安全地在多个 goroutines 之间共享变量。
  9. Error Handling: 在并发编程中,错误处理非常重要。通常,你会通过返回值来传递错误,或者使用 channels 来传递错误信息。
  10. Context: context 包用于在 goroutines 之间传递状态信息,如取消信号或截止时间。这对于编写可取消的并发操作非常有用。
  11. Rate Limiting: 通过使用 golang.org/x/time/rate 包,你可以实现对 goroutines 的速率限制,这对于控制资源使用或防止过载非常有用。
  12. Select with Timeout: 你可以在 select 语句中使用 time.After 函数来实现超时逻辑。