You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复未执行的CANBUS日志函数?Go语言日志写入故障排查

问题分析与解决方案

从你的代码来看,核心问题出在文件生命周期的错误管理上,导致明明进入了写入条件却无法把内容追加到文件里,具体原因和修复方案如下:

关键问题拆解

  1. 文件被提前关闭:在token == false的分支里,你用了defer f.Close()——这个语句会在FileCreatorWriter函数退出时执行,意味着刚创建好文件就被立刻关闭了。后续满足DS == IDds && 1 == frameID条件时,f已经是一个失效的关闭句柄,调用log.SetOutput(f)自然写不进任何内容。
  2. log.SetOutput的误用:你每次触发写入条件都重复调用log.SetOutput(f),但这个函数只需要在文件句柄有效时设置一次即可,重复绑定失效的句柄完全没有意义。

修复后的代码示例

我调整了FileCreatorWriter的逻辑,确保文件在整个日期周期内保持打开状态,只有日期变化时才关闭旧文件并创建新文件:

func FileCreatorWriter(DS int, data []byte) (err error) {
    currentDate := time.Now().Format("01-02-2006")
    // 日期变更时,关闭旧文件(如果存在)并创建新文件
    if datecheck != currentDate {
        // 先关闭之前打开的文件,避免资源泄漏
        if f != nil {
            _ = f.Close()
        }
        datecheck = currentDate
        timestamp := time.Now().Format(" 01-02-2006 - 15:04:05")
        fileName := fmt.Sprintf("IDDS: %d - %s.txt", DS, timestamp)
        f, err = os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
        if err != nil {
            log.Fatalf("error opening file: %v", err)
            return err
        }
        // 仅在打开新文件时设置一次log输出目标
        log.SetOutput(f)
        token = true
    }

    _, frameID = CityFilter.FrameIden(id)
    IDds := CityFilter.ReadIDDS(Converter(data))
    if DS == IDds && 1 == frameID {
        fmt.Printf("I am in!!!!!!")
        // 此时文件处于打开状态,直接写入即可实现追加
        log.Println(datamap)
    }
    return
}

额外优化建议

  • 减少全局变量依赖:全局的f、datecheck、token会让代码逻辑变得晦涩,建议把这些状态封装到一个自定义结构体(比如CANLogger)中,代码可读性和可维护性会大幅提升。
  • 完善错误处理:原代码中defer f.Close()之后的错误处理没有实际意义,建议把错误检查放在文件创建之后立刻处理。
  • 考虑并发安全:你的代码里有goroutine修改state,如果后续日志写入涉及并发操作,建议给文件读写加上sync.Mutex,避免竞态条件导致的异常。

内容的提问来源于stack exchange,提问作者Deniz Tohumcu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:51:58