go log


先看实例

package main

import (
	"log"
	"os"
)

func init() {
	// 配置日志输出格式
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	// 配置前缀
	log.SetPrefix("order:")
	// 配置输出位置
	logFile, err := os.OpenFile("./test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		log.Panic("打开日志文件异常")
	}
	log.SetOutput(logFile)
}

func main() {
	log.Println("测试")
}

输出结果

运行程序,会创建一个test.log文件,文件内容如下:

order:2022/11/23 15:46:56 test.go:22: 测试

你可以多运行几次,修改运行main中输出的内容,观察有何效果。

标准库日志log

log包提供了简单的日志功能,该包中定义了一个结构体Logger,该结构体有一些方法实现日志功能。

Logger结构体

type Logger struct {
    mu        sync.Mutex // ensures atomic writes; protects the following fields
    prefix    string     // prefix on each line to identify the logger (but see Lmsgprefix)
    flag      int        // properties
    out       io.Writer  // destination for output 
    buf       []byte     // for accumulating text to write 
    isDiscard int32      // atomic boolean: whether out == io.Discard
}

mu:是一个互斥锁,保证日志写操作的原子性

prefix:日志的前缀

flag:日志输入的格式

out:输出的目标,例如:控制台、或者文件。

buf:一个缓冲区,提高文本的写速度

isDiscard:一个标记,是否out==io.Discard

日志的输出格式

日志的输出格式可以通过flag标记来控制,可以使用的常量有如下几个:

const (
    Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23
    Ltime                         // the time in the local time zone: 01:23:23
    Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
    Llongfile                     // full file name and line number: /a/b/c/d.go:23
    Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
    LUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zone
    Lmsgprefix                    // move the "prefix" from the beginning of the line to before the message
    LstdFlags     = Ldate | Ltime // initial values for the standard logger
)

例如,Ldate | Ltime 或者 LstdFlags,输出日志格式如下:

2009/01/23 01:23:23 message

例如,Ldate | Ltime | Lmicroseconds | Llongfile,输出日志格式如下:

2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message

日志的前缀配置

func Prefix() string  // 返回日志的前缀配置
func SetPrefix(prefix string)  // 设置日志前缀

日志的输出位置配置

func SetOutput(w io.Writer) {
	std.SetOutput(w)
}

输出位置是一个Writer接口,这意味着实现了改接口的类都可以,可以是标准输出到控制台,也可以是文件,正如我们一开始那个实例所示。

日志堆栈调用深度设置

package main

import (
	"log"
)

func main() {
	logger := log.Default()
	logger.SetFlags(log.Llongfile)
	logger.Output(0, "0 calldepth")
	logger.Output(1, "1 calldepth")
	logger.Output(2, "2 calldepth")
}

运行结果

D:/Environment/go1.19.3/src/log/log.go:185: 0 calldepth
D:/Document/learn/test.go:11: 1 calldepth                   
D:/Environment/go1.19.3/src/runtime/proc.go:250: 2 calldepth

日志的实例化

实例化相关的语句有:

func New(out io.Writer, prefix string, flag int) *Logger {
	l := &Logger{out: out, prefix: prefix, flag: flag}
	if out == io.Discard {
		l.isDiscard = 1
	}
	return l
}

var std = New(os.Stderr, "", LstdFlags)

func Default() *Logger { return std }

实例

package main

import (
	"log"
	"os"
)

func TestLogger() {
	var (
		logger = log.New(os.Stderr, "logger: ", log.Lshortfile)
	)
	logger.Print("我就试试不进去")
}

func main() {
	TestLogger()
}

运行结果

logger: test.go:17: 我就试试不进去

日志输出方法

纯打印日志

Print[f|ln]

打印日志,抛出panic异常

Panic[f|ln]

打印日志,强制结束程序(os.Exit(1)),defer函数不会执行

Fatal[f|ln]

实例

package main

import (
	"fmt"
	"log"
)

func TestLogPrint() {
	//纯粹就是打印日志而已
	log.Printf("%s\n", "TestLogPrintf")
	log.Println("TestLogPrintln")

}

func TestLogPanic() {
	defer fmt.Println("Panic defer")
	log.Panicln("TestLogPanic")
	//运行后发现defer 被执行了,因此panic是等到函数执行完才结束
}

func TestLogFatal() {
	defer fmt.Println("Panic Fatal")
	log.Fatalln("TestLogFatal")
	//运行后发现defer 没被执行了,fatal 是直接结束程序
}

func main() {
	TestLogPrint()
	TestLogPanic()
	// TestLogFatal()
}

运行结果

执行

TestLogPrint()
TestLogPanic()
2022/11/23 16:06:11 TestLogPrintln                      
2022/11/23 16:06:11 TestLogPanic                        
Panic defer                                             
panic: TestLogPanic                                     
                                                        
                                                        
goroutine 1 [running]:                                  
log.Panicln({0xc000109f30?, 0xc000109f60?, 0x467805?})  
        D:/Environment/go1.19.3/src/log/log.go:402 +0x65
main.TestLogPanic()
        D:/Document/learn/test.go:17 +0x94
main.main()
        D:/Document/learn/test.go:29 +0x1c

仅执行 TestLogFatal()

2022/11/23 16:06:31 TestLogFatal

如果本文帮助到了你,帮我点个广告可以咩(o′┏▽┓`o)


评论
 上一篇
go init函数 go init函数
go 的 init 函数,是一个自动执行,不能被调用的函数。一般用于初始化
2022-11-23
下一篇 
go 代理设置 go 代理设置
啥都没写,别看
2022-11-22
  目录