如何修复未执行的CANBUS日志函数?Go语言日志写入故障排查
问题分析与解决方案
从你的代码来看,核心问题出在文件生命周期的错误管理上,导致明明进入了写入条件却无法把内容追加到文件里,具体原因和修复方案如下:
关键问题拆解
- 文件被提前关闭:在
token == false的分支里,你用了defer f.Close()——这个语句会在FileCreatorWriter函数退出时执行,意味着刚创建好文件就被立刻关闭了。后续满足DS == IDds && 1 == frameID条件时,f已经是一个失效的关闭句柄,调用log.SetOutput(f)自然写不进任何内容。 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
相关产品推荐
相关产品推荐

