当前位置: 技术文章>> go语言学习之go日志详解

文章标题:go语言学习之go日志详解
  • 文章分类: 后端
  • 15665 阅读

golang 的log包使用起来挺简单,这里做一些简单介绍。

示例:

package mainimport (   "log")func main() {   arr := []int{1, 2}   log.Print("Print array ", arr, "\n")   log.Println("Println array", arr)   log.Printf("Printf array with item [%d,%d]\n", arr[0], arr[1])}

结果:

2018/12/14 18:42:02 Print array [1 2]
2018/12/14 18:42:02 Println array [1 2]
2018/12/14 18:42:02 Printf array with item [1,2]

log.Fatal 、log.Fatalln、log.Fatalf

示例:

    log.Fatal("Fatal array ", arr, "\n")    log.Fatalln("Fatalln array", arr)    log.Fatalf("Fatalf array with item [%d,%d]\n", arr[0], arr[1])

对于 log.Fatal 接口,会先将日志内容打印到标准输出,接着调用系统的 os.exit(1) 接口退出程序并返回状态 1 。

在实际开发中要慎重,它导致整个系统退出,且不执行defer。

示例

package mainimport (   "fmt"   "log"   "net/http")func sayHelloHandler(w http.ResponseWriter, r *http.Request) {   defer func() {      fmt.Println("--first--")   }()   log.Fatalln("test for defer Fatal")}func main() {   http.HandleFunc("/", sayHelloHandler) //   设置访问路由   log.Fatal(http.ListenAndServe(":8080", nil))}

当访问 http://127.0.0.1:8080/ 后,http 服务停止了,且defer没有调用。

log.SetOutput

将日志写到指定文件中

示例

package mainimport (   "log"   "os")func main() {   // 按照所需读写权限创建文件   f, err := os.OpenFile("filename.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)   if err != nil {      log.Fatal(err)   }   // 完成后延迟关闭   defer f.Close()   //设置日志输出到 f   log.SetOutput(f)   //写入日志内容   log.Println("check to make sure it works")}

查看生成日志文件filename.log 内容

2018/12/14 18:56:55 check to make sure it works

log.Logger、log.New

先自定义Logger类型, log.Logger提供了一个New方法用来创建对象:

func New(out io.Writer, prefix string, flag int) *Logger

该函数一共有三个参数:

(1)输出位置out,是一个io.Writer对象,该对象可以是一个文件也可以是实现了该接口的对象。通常我们可以用这个来指定日志输出到哪个文件。
(2)prefix 我们在前面已经看到,就是在日志内容前面的东西。我们可以将其置为 “[Info]” 、 “[Warning]”等来帮助区分日志级别。
(3) flags 是一个选项,显示日志开头的东西,可选的值有:

Ldate         = 1 << iota     // 形如 2009/01/23 的日期Ltime                         // 形如 01:23:23   的时间Lmicroseconds                 // 形如 01:23:23.123123   的时间Llongfile                     // 全路径文件名和行号: /a/b/c/d.go:23 Lshortfile                    // 文件名和行号: d.go:23LstdFlags     = Ldate | Ltime // 日期和时间
package mainimport (   "io"   "io/ioutil"   "log"   "os")var (   Trace   *log.Logger // 记录所有日志   Info    *log.Logger // 重要的信息   Warning *log.Logger // 需要注意的信息   Error   *log.Logger // 致命错误)func init() {   file, err := os.OpenFile("filename.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)   if err != nil {      log.Fatalln(err)   }   Trace = log.New(ioutil.Discard, "TRACE: ", log.Ltime|log.Lshortfile)   Info = log.New(os.Stdout, "Info: ", log.Ltime|log.Lshortfile)   Warning = log.New(os.Stdout, "Warning: ", log.Ltime|log.Lshortfile)   Error = log.New(io.MultiWriter(file, os.Stderr), "Error", log.Ltime|log.Lshortfile)}func main() {   Trace.Println("trace")   Info.Println("info")   Warning.Println("warning")   Error.Println("Error")}

细心的朋友可能发现执行多次程序输出日志的顺序会有变化,这个主要是 os.Stderr和os.Stdout输出的不同引起的,这两个虽然都是输出到终端,但在默认情况下,stdout是行缓冲的,它的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。而stderr是无缓冲的,会直接输出的。参考:http://blog.sina.com.cn/s/blog_912673ce01013qq9.html

日志库logrus

logrus是在Github中star最多的go日志库,功能强大,性能不错。

安装:

go get -u github.com/sirupsen/logrus

实例

package mainimport (   "github.com/sirupsen/logrus"   "os")// Create a new instance of the logger. You can have any number of instances.var log = logrus.New()func main() {   // The API for setting attributes is a little different than the package level   // exported logger. See Godoc.   log.Out = os.Stdout   //You could set this to any `io.Writer` such as a file   file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)   if err == nil {      log.Out = file   } else {      log.Info("Failed to log to file, using default stderr")   }   log.WithFields(logrus.Fields{      "animal": "walrus",      "size":   10,   }).Info("A group of walrus emerges from the ocean")}

如果你对别的Go日志库感兴趣可以参考:


推荐文章