quick start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"log"
)

type User struct {
Name string
Age int
}

func main() {
u := User{
Name: "dj",
Age: 18,
}

log.Printf("%s login, age:%d", u.Name, u.Age)
log.Panicf("Oh, system error when %s login", u.Name)
log.Fatalf("Danger! hacker %s login", u.Name)
}

log默认输出到标准错误(stderr),每条日志前会自动加上日期和时间。

如果日志不是以换行符结尾的,那么log会自动加上换行符。即每条日志会在新行中输出

log提供了三组函数:

  • Print/Printf/Println:正常输出日志;
  • Panic/Panicf/Panicln:输出日志后,以拼装好的字符串为参数调用panic
  • Fatal/Fatalf/Fatalln:输出日志后,调用os.Exit(1)退出程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/log/log.go
var std = New(os.Stderr, "", LstdFlags)

func Printf(format string, v ...interface{}) {
std.Output(2, fmt.Sprintf(format, v...))
}

func Fatalf(format string, v ...interface{}) {
std.Output(2, fmt.Sprintf(format, v...))
os.Exit(1)
}

func Panicf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
std.Output(2, s)
panic(s)
}

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package log

import (
"io/ioutil"
"log"
"os"
"sync"
)

var (
errorLog = log.New(os.Stdout, "\033[31m[error]\033[0m ", log.LstdFlags|log.Lshortfile)
infoLog = log.New(os.Stdout, "\033[34m[info ]\033[0m ", log.LstdFlags|log.Lshortfile)
loggers = []*log.Logger{errorLog, infoLog}
mu sync.Mutex
)

// log methods
var (
Error = errorLog.Println
Errorf = errorLog.Printf
Info = infoLog.Println
Infof = infoLog.Printf
)

// log levels
const (
InfoLevel = iota
ErrorLevel
Disabled
)

// SetLevel controls log level
func SetLevel(level int) {
mu.Lock()
defer mu.Unlock()

for _, logger := range loggers {
logger.SetOutput(os.Stdout)
}

// 通过控制 Output,来控制日志是否打印。
// 如果设置为 ErrorLevel,infoLog 的输出会被定向到 ioutil.Discard,即不打印该日志。
if ErrorLevel < level {
errorLog.SetOutput(ioutil.Discard)
}
if InfoLevel < level {
infoLog.SetOutput(ioutil.Discard)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package log

import (
"os"
"testing"
)

func TestSetLevel(t *testing.T) {
SetLevel(ErrorLevel)
if infoLog.Writer() == os.Stdout || errorLog.Writer() != os.Stdout {
t.Fatal("failed to set log level")
}
SetLevel(Disabled)
if infoLog.Writer() == os.Stdout || errorLog.Writer() == os.Stdout {
t.Fatal("failed to set log level")
}
}