MST

星途 面试题库

面试题:Go中通道在协程通信里的基础应用

请用Go语言编写一个简单示例,包含两个协程,一个协程向通道发送数字1 - 10,另一个协程从通道接收并打印这些数字。同时,请解释通道在这个过程中的作用以及如何防止协程泄露。
17.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
)

func sender(ch chan int) {
    for i := 1; i <= 10; i++ {
        ch <- i
    }
    close(ch)
}

func receiver(ch chan int) {
    for num := range ch {
        fmt.Println(num)
    }
}

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

    select {}
}

通道在这个过程中的作用

  1. 数据传递:通道 ch 作为两个协程之间的数据桥梁,sender 协程通过 ch <- i 将数字发送到通道,receiver 协程通过 num := <-ch 从通道接收数字,实现了数据在不同协程间的传递。
  2. 同步:通道的发送和接收操作是阻塞的。例如,当 sender 向通道发送数据时,如果此时没有 receiver 来接收,sender 协程会阻塞,直到有 receiver 接收数据;反之,receiver 协程在尝试从通道接收数据时,如果没有数据发送进来,receiver 也会阻塞,直到有数据可用。这种阻塞机制确保了协程之间的同步。

防止协程泄露的方法

  1. 关闭通道:在 sender 协程完成数据发送后,使用 close(ch) 关闭通道。这不仅可以告知 receiver 协程数据发送已结束,避免 receiver 无限期阻塞,还能让 receiver 中的 for... range 循环正常退出。如果不关闭通道,receiver 协程会一直阻塞在接收操作上,导致协程泄露。
  2. 正确使用 select:在 main 函数中,使用 select {} 来阻塞 main 函数的退出。因为 main 函数是程序的主协程,如果 main 函数结束,整个程序就会终止,不管其他协程是否完成。select {} 会使 main 协程永远阻塞,从而保证 senderreceiver 协程有足够的时间完成它们的任务。