MST
星途 面试题库

面试题:Go语言中复杂定时任务的协程实现

假设需要实现一个定时任务,每隔3秒执行一次某个复杂的业务逻辑(比如从数据库读取数据并处理),同时在每次任务执行完后等待2秒再进行下一次执行。请用Go语言编写完整代码,并解释如何优雅地处理可能出现的错误以及如何安全地停止这个定时任务。
24.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

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

func complexBusinessLogic(ctx context.Context) error {
    // 模拟从数据库读取数据并处理
    fmt.Println("开始执行复杂业务逻辑")
    time.Sleep(2 * time.Second)
    fmt.Println("复杂业务逻辑执行完毕")

    // 这里简单返回nil表示无错误,实际中根据业务处理返回具体错误
    return nil
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())

    go func() {
        for {
            select {
            case <-ctx.Done():
                return
            default:
                err := complexBusinessLogic(ctx)
                if err != nil {
                    log.Printf("执行复杂业务逻辑出错: %v", err)
                }
                time.Sleep(2 * time.Second)
            }
            time.Sleep(3 * time.Second)
        }
    }()

    // 模拟运行10秒后停止任务
    time.Sleep(10 * time.Second)
    cancel()
    fmt.Println("定时任务已停止")
}

错误处理

  1. 业务逻辑错误:在complexBusinessLogic函数中,实际的数据库读取和处理操作可能会返回错误。在示例代码中,complexBusinessLogic简单返回nil,实际应用中应根据具体的数据库操作返回相应的错误。在调用complexBusinessLogic的地方,通过if err != nil判断并使用log.Printf记录错误信息,这样可以方便调试和排查问题。
  2. 其他潜在错误:如context相关操作可能出现的错误,由于context.WithCancel操作通常不会失败,所以这里不需要额外处理其错误。但如果是使用context.WithTimeout等操作,可能需要处理context创建时返回的错误。

安全停止定时任务

  1. 使用context:通过context.WithCancel创建一个可取消的context,并传递给complexBusinessLogic函数和select语句中的ctx.Done()通道。当调用cancel()函数时,ctx.Done()通道会收到信号,从而跳出for循环,安全停止定时任务。
  2. 避免资源泄露:在complexBusinessLogic函数内部,如果涉及到数据库连接等资源,应确保在函数返回时正确关闭资源,避免资源泄露。在示例代码中虽然是模拟的业务逻辑,但实际应用中要特别注意这一点。