MST

星途 面试题库

面试题:Go语言中如何实现简单的事件驱动模型

在Go语言里,通常会使用goroutine和channel来构建事件驱动模型。请你编写一个简单示例,模拟一个事件生产者和多个事件消费者的场景,生产者持续生成整数事件,消费者负责接收并打印这些事件。同时说明在这个模型中,goroutine和channel分别起到什么作用。
48.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
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)
    }
}

在上述代码中,通过以下方式使用goroutinechannel构建事件驱动模型:

  1. goroutine的作用
    • goroutine实现了轻量级的并发执行。在主函数中,通过go producer(out)启动了一个生产者goroutine,这个goroutine会在后台独立运行,不断地生成整数事件并发送到channel中。同时,通过go consumer(in, j)启动了多个消费者goroutine,每个消费者goroutine也在后台独立运行,从channel接收事件并进行处理(这里是打印)。多个goroutine可以并行处理任务,充分利用多核CPU的优势,提高程序的并发性能。
  2. channel的作用
    • channelgoroutine之间通信的桥梁。生产者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可以持续运行。