package logger import ( "fmt" "os" "path/filepath" "sync" "time" ) var ( baseDir string mu sync.Mutex ) // Init 初始化日志根目录(例如 logs/server),应在 main 中调用 func Init(dir string) { baseDir = filepath.Clean(dir) _ = os.MkdirAll(baseDir, 0755) } // pathFile 返回 path 对应的 .log 或 .err 的完整路径;path 如 "main" 或 "handlers/auth" func pathFile(path, ext string) string { // 安全化:只保留路径分隔符和字母数字 clean := filepath.Clean(path) if clean == "" || clean == "." { clean = "main" } full := filepath.Join(baseDir, clean+ext) dir := filepath.Dir(full) _ = os.MkdirAll(dir, 0755) return full } func appendLine(fpath, line string) { if baseDir == "" || fpath == "" { return } mu.Lock() defer mu.Unlock() f, err := os.OpenFile(fpath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if err != nil { return } defer f.Close() _, _ = f.WriteString(line) } func line(level, format string, a ...interface{}) string { return fmt.Sprintf("%s [%s] %s\n", time.Now().Format("2006-01-02 15:04:05"), level, fmt.Sprintf(format, a...)) } // Log 写普通日志:写入 log.log(简单总日志)和 path 对应的 xxx.log(按路径的详细日志) func Log(path, format string, a ...interface{}) { msg := line("INFO", format, a...) appendLine(filepath.Join(baseDir, "log.log"), msg) appendLine(pathFile(path, ".log"), msg) } // Err 写报错:写入 path 对应的 xxx.err(仅报错)、xxx.log 和 log.log func Err(path, format string, a ...interface{}) { msg := line("ERROR", format, a...) appendLine(pathFile(path, ".err"), msg) appendLine(pathFile(path, ".log"), msg) appendLine(filepath.Join(baseDir, "log.log"), msg) }