MST

星途 面试题库

面试题:Go语言中Go生成器在简单并发场景的应用

请描述在Go语言中,如何使用Go生成器(generator,通常通过channel和goroutine模拟实现)来处理并发任务,假设有多个任务需要并发执行,每个任务从生成器获取数据进行处理,最后汇总结果。请给出简单的代码示例及说明。
20.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,我们可以通过channel和goroutine来模拟生成器实现并发任务处理。以下是一个简单的示例代码及说明:

package main

import (
    "fmt"
)

// 生成器函数,通过channel返回数据
func generator(nums...int) <-chan int {
    out := make(chan int)
    go func() {
        for _, num := range nums {
            out <- num
        }
        close(out)
    }()
    return out
}

// 处理任务的函数,从channel获取数据并处理
func worker(id int, in <-chan int, out chan<- int) {
    for num := range in {
        fmt.Printf("Worker %d processing %d\n", id, num)
        result := num * num // 简单的处理,例如求平方
        out <- result
    }
}

// 汇总结果的函数
func collector(in <-chan int) []int {
    var results []int
    for result := range in {
        results = append(results, result)
    }
    return results
}

func main() {
    data := []int{1, 2, 3, 4, 5}
    gen := generator(data...)

    const numWorkers = 3
    var workerOuts = make([]chan int, numWorkers)
    for i := 0; i < numWorkers; i++ {
        workerOuts[i] = make(chan int)
        go worker(i, gen, workerOuts[i])
    }

    var finalOut = make(chan int)
    go func() {
        for _, out := range workerOuts {
            for result := range out {
                finalOut <- result
            }
        }
        close(finalOut)
    }()

    results := collector(finalOut)
    fmt.Println("Final results:", results)
}

代码说明

  1. 生成器函数(generator

    • 接受可变参数nums,创建一个只写的channel out
    • 在一个新的goroutine中,将参数nums中的数据逐个发送到out channel,发送完毕后关闭channel
    • 最后返回这个只读的channel out
  2. 工作函数(worker

    • 接受id(标识工作者)、输入channel in和输出channel out
    • 从输入channel in中读取数据,进行处理(这里简单地求平方),然后将结果发送到输出channel out
  3. 汇总函数(collector

    • 接受一个只读channel in,从该channel中读取所有结果,并将其收集到一个切片results中,最后返回这个切片。
  4. 主函数(main

    • 定义了一个数据切片data
    • 通过generator函数创建一个生成器gen
    • 创建多个worker,每个worker从生成器gen获取数据并处理,将结果发送到各自的输出channel workerOuts
    • 再通过一个匿名goroutine将所有worker的输出channel中的结果汇总到finalOut channel
    • 最后通过collector函数收集finalOut channel中的所有结果并打印。