MST

星途 面试题库

面试题:Go实现高效通知退出机制的基础方式

在Go语言中,简单描述如何使用context包来实现一个基本的通知退出机制。请写出关键代码片段,并解释每个部分的作用。
18.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 关键代码片段
package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    // 创建一个带有取消功能的上下文
    ctx, cancel := context.WithCancel(context.Background())

    // 启动一个goroutine
    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("收到退出通知,退出goroutine")
                return
            default:
                fmt.Println("工作中...")
                time.Sleep(1 * time.Second)
            }
        }
    }(ctx)

    // 模拟一段时间后取消
    time.Sleep(3 * time.Second)
    cancel()
    time.Sleep(1 * time.Second)
}
  1. 代码解释
    • 创建上下文和取消函数
      ctx, cancel := context.WithCancel(context.Background())
      
      • context.Background() 是Go语言中所有上下文的根上下文。它通常用于程序的顶层。
      • context.WithCancel(parent) 函数创建了一个新的上下文 ctx 和一个取消函数 cancel。这个新的上下文可以被取消,当 cancel 函数被调用时,所有基于这个上下文派生的子上下文都会收到取消信号。
    • goroutine中的逻辑
      go func(ctx context.Context) {
          for {
              select {
              case <-ctx.Done():
                  fmt.Println("收到退出通知,退出goroutine")
                  return
              default:
                  fmt.Println("工作中...")
                  time.Sleep(1 * time.Second)
              }
          }
      }(ctx)
      
      • 在这个匿名的goroutine中,使用 select 语句监听 ctx.Done() 通道。当这个通道接收到数据时,意味着上下文被取消,ctx.Done() 通道会被关闭,此时goroutine打印收到退出通知并返回,结束运行。
      • default 分支在 ctx.Done() 通道没有数据时执行,模拟goroutine的正常工作,这里打印“工作中...”并休眠1秒。
    • 主函数中的逻辑
      time.Sleep(3 * time.Second)
      cancel()
      time.Sleep(1 * time.Second)
      
      • time.Sleep(3 * time.Second) 模拟主程序运行一段时间。
      • cancel() 调用取消函数,向基于 ctx 的所有上下文发送取消信号。
      • time.Sleep(1 * time.Second) 确保在主程序退出前,有足够的时间让goroutine处理取消信号并退出。