MST

星途 面试题库

面试题:Go语言标签与跳转在并发编程中的精妙应用

在一个Go语言的并发程序中,有多个goroutine并行处理任务。每个goroutine负责从一个共享的任务队列中取出任务并处理。当某个特定任务(例如任务ID为100的任务)被处理完成后,需要通过标签与跳转机制,通知所有其他正在运行的goroutine停止当前任务处理并优雅退出。请设计并实现这个并发程序架构,详细阐述标签与跳转在其中的设计思路与具体作用。
23.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 任务队列:使用Go语言的channel作为共享的任务队列,用于各个goroutine获取任务。
  2. 停止信号:定义一个全局的stop channel,当特定任务完成时,向这个channel发送信号,通知其他goroutine停止。
  3. 标签与跳转:这里的“标签与跳转”类似一种协调机制,在Go语言中可以通过select语句结合stop channel来实现类似功能。select语句会阻塞直到其某个case分支可以继续执行,这样就可以实现类似跳转等待特定信号的效果。

具体实现

package main

import (
    "fmt"
    "sync"
)

type Task struct {
    ID int
    // 其他任务相关字段
}

func worker(taskQueue <-chan Task, stop <-chan struct{}, wg *sync.WaitGroup) {
    defer wg.Done()
    for {
        select {
        case task, ok := <-taskQueue:
            if!ok {
                return
            }
            if task.ID == 100 {
                // 处理特定任务
                fmt.Println("处理特定任务ID为100")
                close(stop) // 通知其他goroutine停止
            } else {
                // 处理其他任务
                fmt.Println("处理任务ID:", task.ID)
            }
        case <-stop:
            return
        }
    }
}

func main() {
    var wg sync.WaitGroup
    taskQueue := make(chan Task)
    stop := make(chan struct{})

    // 启动多个goroutine
    numWorkers := 3
    for i := 0; i < numWorkers; i++ {
        wg.Add(1)
        go worker(taskQueue, stop, &wg)
    }

    // 模拟添加任务
    tasks := []Task{
        {ID: 1},
        {ID: 100},
        {ID: 2},
    }
    for _, task := range tasks {
        taskQueue <- task
    }
    close(taskQueue)

    wg.Wait()
    fmt.Println("所有goroutine已停止")
}

标签与跳转的作用

  1. 标签作用:在这个程序中,特定任务ID(100)就相当于一个“标签”,通过判断任务的ID来识别特定任务。
  2. 跳转作用select语句中的case <-stop:分支就相当于“跳转”,一旦stop channel接收到信号,goroutine就会从处理任务的流程跳转到退出流程,从而优雅停止当前任务处理并退出。这种机制使得goroutine之间可以有效地进行通信和协调,实现并发程序的有序停止。