面试题答案
一键面试使用Channel实现两个Goroutine间简单数据传递
以下是一个示例代码,展示如何在Go语言中使用Channel实现两个Goroutine之间传递整数序列:
package main
import (
"fmt"
)
// 生成整数序列的Goroutine
func generateNumbers(ch chan int) {
for i := 1; i <= 5; i++ {
ch <- i // 将整数发送到Channel
}
close(ch) // 关闭Channel
}
// 接收并打印整数的Goroutine
func printNumbers(ch chan int) {
for num := range ch { // 从Channel接收数据,直到Channel关闭
fmt.Println("Received:", num)
}
}
在main
函数中启动这两个Goroutine:
func main() {
ch := make(chan int)
go generateNumbers(ch)
go printNumbers(ch)
// 防止主线程退出
select {}
}
无缓冲和有缓冲Channel的区别
-
无缓冲Channel:
- 定义:通过
make(chan Type)
创建,没有指定缓冲区大小。 - 特点:
- 发送操作(
ch <- value
)和接收操作(<- ch
)是同步的。也就是说,当一个Goroutine向无缓冲Channel发送数据时,它会阻塞,直到另一个Goroutine从该Channel接收数据。反之亦然。 - 这种同步特性确保了数据传递的即时性和确定性。
- 发送操作(
- 应用场景:
- 用于需要严格同步的场景,例如在两个Goroutine之间进行握手(handshake)操作。比如一个Goroutine等待另一个Goroutine完成某个初始化步骤后再继续执行。
- 确保数据传递的顺序性,因为发送和接收是一一对应的,不会出现数据乱序的情况。
- 定义:通过
-
有缓冲Channel:
- 定义:通过
make(chan Type, capacity)
创建,其中capacity
指定了缓冲区的大小。 - 特点:
- 发送操作在缓冲区未满时不会阻塞,接收操作在缓冲区不为空时不会阻塞。只有当缓冲区满了,发送操作才会阻塞;当缓冲区空了,接收操作才会阻塞。
- 可以容纳一定数量的数据,提供了一定的异步性。
- 应用场景:
- 用于解耦生产者 - 消费者模型。生产者Goroutine可以快速地向有缓冲Channel发送数据,而不需要等待消费者Goroutine立即接收,只要缓冲区未满即可。
- 在一些需要一定数据缓冲以应对瞬时高并发的场景中,有缓冲Channel可以缓解数据处理的压力,避免频繁的阻塞和唤醒操作。
- 定义:通过