面试题答案
一键面试1. 构建简单生产者消费者模型
在Go语言中,通过chan
(通道)构建简单生产者消费者模型示例代码如下:
package main
import (
"fmt"
)
func producer(ch chan int) {
for i := 0; i < 10; i++ {
ch <- i
fmt.Printf("Produced: %d\n", i)
}
close(ch)
}
func consumer(ch chan int) {
for num := range ch {
fmt.Printf("Consumed: %d\n", num)
}
}
在main
函数中调用:
func main() {
ch := make(chan int)
go producer(ch)
consumer(ch)
}
2. 性能优化措施
- 避免不必要的阻塞:
- 非阻塞发送和接收:可以使用
select
语句结合default
分支进行非阻塞操作。例如,在生产者中,如果通道已满但又不想阻塞,可以这样做:
- 非阻塞发送和接收:可以使用
func producer(ch chan int) {
for i := 0; i < 10; i++ {
select {
case ch <- i:
fmt.Printf("Produced: %d\n", i)
default:
fmt.Printf("Channel is full, skip producing %d\n", i)
}
}
close(ch)
}
- **超时机制**:同样使用`select`语句结合`time.After`函数设置超时。例如在消费者中,如果等待接收数据超时,可以执行其他逻辑:
func consumer(ch chan int) {
for {
select {
case num, ok := <-ch:
if!ok {
return
}
fmt.Printf("Consumed: %d\n", num)
case <-time.After(1 * time.Second):
fmt.Println("Timeout waiting for data")
}
}
}
- 合理设置chan的缓冲区大小:
- 无缓冲通道:无缓冲通道(如
ch := make(chan int)
)在发送和接收操作时会阻塞,直到另一端准备好,适用于需要同步的场景,确保生产者和消费者严格交替执行。 - 有缓冲通道:有缓冲通道(如
ch := make(chan int, 5)
)允许在缓冲区未满时发送数据而不阻塞。合理设置缓冲区大小要根据具体场景,比如已知生产者生产数据的频率远高于消费者消费数据的频率,且内存允许,可以适当增大缓冲区,以减少生产者阻塞的时间。但缓冲区过大可能会占用过多内存,且数据在缓冲区停留时间过长可能导致处理延迟。
- 无缓冲通道:无缓冲通道(如