first look at the example
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("测试")
}
output result
Running the program will create a test.log
file with the following content:
order:2022/11/23 15:46:56 test.go:22: 测试
You can run it several times, modify the content output in running main, and observe the effect.
Standard library log log
The log package provides a simple log function. A structure is defined in the package Logger
, and the structure has some methods to implement the log function.
Logger structure
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
: It is a mutex to ensure the atomicity of log write operations
prefix
: prefix for logs
flag
: format of log input
out
: The target of the output, for example: console, or file.
buf
: a buffer that improves text writing speed
isDiscard
: a flag, whetherout==io.Discard
log output format
The output format of the log can be controlled by the flag tag, and the constants that can be used are as follows:
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
)
For example, Ldate | Ltime
or LstdFlags
, the output log format is as follows:
2009/01/23 01:23:23 message
For example, Ldate | Ltime | Lmicroseconds | Llongfile
, the output log format is as follows:
2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
Log prefix configuration
func Prefix() string // 返回日志的前缀配置
func SetPrefix(prefix string) // 设置日志前缀
Log output location configuration
func SetOutput(w io.Writer) {
std.SetOutput(w)
}
The output location is an Writer
interface, which means that any class that implements the interface can be used, it can be the standard output to the console, or it can be a file, as we showed in the example at the beginning.
Log stack call depth setting
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")
}
operation result
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
instantiation of the log
The statements related to instantiation are:
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 }
example
package main
import (
"log"
"os"
)
func TestLogger() {
var (
logger = log.New(os.Stderr, "logger: ", log.Lshortfile)
)
logger.Print("我就试试不进去")
}
func main() {
TestLogger()
}
operation result
logger: test.go:17: 我就试试不进去
Log output method
Pure print log
Print[f|ln]
Print the log and throw a panic exception
Panic[f|ln]
Print the log, force the end of the program ( os.Exit(1)
), defer
the function will not be executed
Fatal[f|ln]
example
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()
}
operation result
implement
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
Execute only TestLogFatal()
2022/11/23 16:06:31 TestLogFatal