MST

星途 面试题库

面试题:Go中如何通过通道和Goroutine处理复杂的任务依赖关系

假设有三个任务A、B、C,任务B依赖任务A的结果,任务C依赖任务B的结果。请使用通道和Goroutine设计并实现一个程序来处理这种任务依赖关系,并且说明如何避免死锁等问题。
43.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
)

func main() {
    aChan := make(chan int)
    bChan := make(chan int)
    cChan := make(chan int)

    go taskA(aChan)
    go taskB(aChan, bChan)
    go taskC(bChan, cChan)

    resultC := <-cChan
    fmt.Println("最终结果:", resultC)
    close(aChan)
    close(bChan)
    close(cChan)
}

func taskA(out chan<- int) {
    // 模拟任务A的计算
    result := 10
    out <- result
    close(out)
}

func taskB(in <-chan int, out chan<- int) {
    data := <-in
    // 模拟任务B依赖任务A结果的计算
    result := data * 2
    out <- result
    close(out)
}

func taskC(in <-chan int, out chan<- int) {
    data := <-in
    // 模拟任务C依赖任务B结果的计算
    result := data + 5
    out <- result
    close(out)
}

避免死锁的方法

  1. 确保所有通道都有发送者和接收者:在上述代码中,每个通道都有对应的发送和接收操作,避免因通道操作不匹配导致死锁。例如,taskAaChan 发送数据,taskBaChan 接收数据。
  2. 及时关闭通道:在每个任务完成发送数据后,及时关闭通道。如 taskAtaskBtaskC 完成计算并发送数据后,都调用 close 关闭通道。这可以防止接收者在通道关闭且无数据时永远阻塞。
  3. 合理安排Goroutine的启动顺序:在 main 函数中,按照任务依赖顺序启动 Goroutine,确保依赖在前的任务先执行。同时,main 函数中最后从 cChan 接收数据,避免 main 函数提前退出导致其他 Goroutine 未完成就结束程序。