Golang中如何为包创建日志文件

Golang中如何为包创建日志文件 我的项目包含许多文件和函数。我想创建一个日志文件来了解哪些函数被调用。这个日志文件将对整个包通用。

我知道如何为单个文件创建日志文件,但不知道如何为整个包创建。

单个文件的代码:

package main

import (
	"log"
	"os"
)

func main() {
	file, err := os.OpenFile("sam.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)

	if err != nil {
		log.Fatalln("failed")
	}

	log.SetOutput(file)

	log.Println("this is log file")
	log.Println("this is test\n")
	add()
	sub()
}
func add() {
	log.Println("thi is add\n")
}
func sub() {
	log.Println("thi is sub\n")
}
  1. 如何为项目或文件夹或包创建通用的日志文件
  2. 上面的代码会在文件中单行添加注释,我希望它们能逐行输入

更多关于Golang中如何为包创建日志文件的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

这种方法在REST服务器中是否安全?在可能有数千个线程尝试写入日志文件的情况下,它会在哪里缓冲传入的写入尝试?

更多关于Golang中如何为包创建日志文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


file, err := os.OpenFile("sam.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil { log.Fatalln("failed") }

logger := log.New(file, "my super logger: ", log.Lshortfile)

现在你可以使用 logger.XXX 进行操作。如果需要在代码的其他部分使用此功能,你必须将 logger 变量作为 *log.Logger 类型进行传递。在程序结束前关闭日志文件也是一个良好的实践。

package logg

import (
	"log"
	"os"
)
func Loggi(s string) {
	file, err := os.OpenFile("mygo1.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	defer file.Close()
	if err != nil {
		log.Fatalln("failed")
	}
	log.SetOutput(file)
	log.Println(s)
}

即使创建多个线程这个方法也不会生效,但我可以接受,因为我只会在调试时创建一个线程。

它可以在多个Go协程中正常工作。日志包使用了每个日志的互斥锁,因此如果一个Go协程正在调用log.Println(),其他协程会停止直到互斥锁被解锁。

https://golang.org/src/log/log.go?s=9298:9328#L307

func Println(v ...interface{}) {
	std.Output(2, fmt.Sprintln(v...))
}

调用使用了互斥锁的Output方法

https://golang.org/src/log/log.go?s=9298:9328#L143

// Output writes the output for a logging event. The string s contains
// the text to print after the prefix specified by the flags of the
// Logger. A newline is appended if the last character of s is not
// already a newline. Calldepth is used to recover the PC and is
// provided for generality, although at the moment on all pre-defined
// paths it will be 2.
func (l *Logger) Output(calldepth int, s string) error {
	now := time.Now() // get this early.
	var file string
	var line int
	l.mu.Lock()

在Go语言中,为整个包创建共享的日志文件可以通过包级别的变量和初始化函数来实现。以下是完整的解决方案:

package main

import (
    "log"
    "os"
    "sync"
)

// 包级别的日志文件和互斥锁
var (
    logFile *os.File
    logMutex sync.Mutex
)

// init函数在包初始化时自动执行
func init() {
    var err error
    logFile, err = os.OpenFile("package_log.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalf("Failed to open log file: %v", err)
    }
    
    // 设置日志输出到文件
    log.SetOutput(logFile)
    
    // 设置日志标志,确保每条日志单独一行
    log.SetFlags(log.LstdFlags)
}

// 包级别的日志函数
func LogFunctionCall(funcName string) {
    logMutex.Lock()
    defer logMutex.Unlock()
    log.Printf("Function called: %s\n", funcName)
}

func main() {
    LogFunctionCall("main")
    log.Println("Application started")
    
    add()
    sub()
    multiply()
    
    log.Println("Application finished")
}

func add() {
    LogFunctionCall("add")
    log.Println("Executing add function")
    // 函数逻辑
}

func sub() {
    LogFunctionCall("sub") 
    log.Println("Executing sub function")
    // 函数逻辑
}

func multiply() {
    LogFunctionCall("multiply")
    log.Println("Executing multiply function")
    // 函数逻辑
}

// 在程序结束时关闭日志文件(可选)
func CloseLogFile() {
    if logFile != nil {
        logFile.Close()
    }
}

如果你有多个文件在同一个包中,可以在每个文件中使用相同的日志机制:

file1.go:

package main

func someFunction() {
    LogFunctionCall("someFunction")
    log.Println("This is from file1.go")
}

file2.go:

package main

func anotherFunction() {
    LogFunctionCall("anotherFunction") 
    log.Println("This is from file2.go")
}

对于更复杂的项目结构,你可以创建一个专门的日志包:

logger/logger.go:

package logger

import (
    "log"
    "os"
    "sync"
)

var (
    instance *log.Logger
    once     sync.Once
)

// GetLogger 返回单例日志实例
func GetLogger() *log.Logger {
    once.Do(func() {
        file, err := os.OpenFile("project_log.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
        if err != nil {
            log.Fatal("Failed to create log file:", err)
        }
        
        instance = log.New(file, "APP: ", log.LstdFlags|log.Lshortfile)
    })
    return instance
}

// LogCall 记录函数调用
func LogCall(funcName string) {
    logger := GetLogger()
    logger.Printf("CALL: %s", funcName)
}

在其他包中使用:

package main

import "yourproject/logger"

func someFunction() {
    logger.LogCall("someFunction")
    logger.GetLogger().Println("Function execution details")
}

这样就能确保整个包(或整个项目)使用同一个日志文件,并且每条日志都会单独成行输出。

回到顶部