面试题答案
一键面试package main
import (
"fmt"
)
// 生产者函数,不断向channel发送整数事件
func producer(out chan<- int) {
for i := 0; ; i++ {
out <- i
}
}
// 消费者函数,从channel接收并打印事件
func consumer(in <-chan int, id int) {
for val := range in {
fmt.Printf("Consumer %d received: %d\n", id, val)
}
}
在上述代码中,通过以下方式使用goroutine
和channel
构建事件驱动模型:
goroutine
的作用:goroutine
实现了轻量级的并发执行。在主函数中,通过go producer(out)
启动了一个生产者goroutine
,这个goroutine
会在后台独立运行,不断地生成整数事件并发送到channel
中。同时,通过go consumer(in, j)
启动了多个消费者goroutine
,每个消费者goroutine
也在后台独立运行,从channel
接收事件并进行处理(这里是打印)。多个goroutine
可以并行处理任务,充分利用多核CPU的优势,提高程序的并发性能。
channel
的作用:channel
是goroutine
之间通信的桥梁。生产者goroutine
通过out chan<- int
类型的channel
(只写channel
)向其发送整数事件,消费者goroutine
通过in <-chan int
类型的channel
(只读channel
)从其接收事件。channel
保证了数据在不同goroutine
之间的安全传递,实现了生产者 - 消费者模型中的解耦,使得生产者和消费者不需要直接相互了解,只需要通过channel
进行数据交互,从而让并发编程更加安全和可控。
下面是完整的主函数来运行上述逻辑:
func main() {
out := make(chan int)
// 启动生产者
go producer(out)
// 启动3个消费者
for j := 0; j < 3; j++ {
go consumer(out, j)
}
// 防止主函数退出
select {}
}
在main
函数中,创建了一个channel
,启动了生产者和多个消费者goroutine
,最后通过select {}
阻塞主函数,防止主函数退出,使得生产者和消费者goroutine
可以持续运行。