MST

星途 面试题库

面试题:Go语言中Goroutine的基本并发模式及应用场景

请阐述Go语言中Goroutine常见的并发模式,如生产者 - 消费者模式,并举例说明在实际项目中,什么样的场景适合使用该模式。
38.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Goroutine常见并发模式

  1. 生产者 - 消费者模式
    • 模式描述:生产者负责生成数据,消费者负责处理数据。两者通过通道(channel)进行数据传递。这种模式解耦了数据的生产和消费过程,提高了程序的并发处理能力。
    • 示例代码
package main

import (
    "fmt"
)

func producer(out chan<- int) {
    for i := 0; i < 10; i++ {
        out <- i
    }
    close(out)
}

func consumer(in <-chan int) {
    for num := range in {
        fmt.Println("Consumed:", num)
    }
}

func main() {
    ch := make(chan int)
    go producer(ch)
    consumer(ch)
}
  1. 扇入(Fan - In)模式
    • 模式描述:多个输入通道的数据被合并到一个输出通道。通常用于多个生产者的数据汇总。
    • 示例代码
package main

import (
    "fmt"
)

func producer1(out chan<- int) {
    for i := 0; i < 5; i++ {
        out <- i * 2
    }
    close(out)
}

func producer2(out chan<- int) {
    for i := 0; i < 5; i++ {
        out <- i * 3
    }
    close(out)
}

func fanIn(in1, in2 <-chan int, out chan<- int) {
    go func() {
        for num := range in1 {
            out <- num
        }
    }()
    go func() {
        for num := range in2 {
            out <- num
        }
    }()
    go func() {
        // 等待两个输入通道关闭
        <-in1
        <-in2
        close(out)
    }()
}

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    out := make(chan int)

    go producer1(ch1)
    go producer2(ch2)
    go fanIn(ch1, ch2, out)

    for num := range out {
        fmt.Println("Fan - In:", num)
    }
}
  1. 扇出(Fan - Out)模式
    • 模式描述:一个输入通道的数据被分发到多个输出通道,通常用于将任务分发给多个消费者并行处理。
    • 示例代码
package main

import (
    "fmt"
)

func fanOut(in <-chan int, out1, out2 chan<- int) {
    for num := range in {
        select {
        case out1 <- num:
        case out2 <- num:
        }
    }
    close(out1)
    close(out2)
}

func consumer1(in <-chan int) {
    for num := range in {
        fmt.Println("Consumer1:", num)
    }
}

func consumer2(in <-chan int) {
    for num := range in {
        fmt.Println("Consumer2:", num)
    }
}

func main() {
    in := make(chan int)
    out1 := make(chan int)
    out2 := make(chan int)

    go func() {
        for i := 0; i < 10; i++ {
            in <- i
        }
        close(in)
    }()

    go fanOut(in, out1, out2)
    go consumer1(out1)
    go consumer2(out2)

    select {}
}

生产者 - 消费者模式适用场景

  1. 任务队列处理:例如在一个Web应用中,有大量的任务需要处理,如图片处理、视频转码等。可以将这些任务作为数据由生产者放入任务队列(通道),消费者从队列中取出任务并处理。这样可以避免任务堆积在单个处理单元,提高整体处理效率。
  2. 数据采集与分析:在大数据采集场景中,数据采集模块作为生产者,不断地从各种数据源采集数据并放入通道。数据分析模块作为消费者,从通道中获取数据进行分析处理。这种模式可以保证数据采集和分析的解耦,即使数据采集速度和分析速度不匹配,也能通过通道缓冲进行协调。