原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://gotaly.blog.51cto.com/8861157/1405754

Golang的标准库提供了log的机制,但是该模块的功能较为简单(看似简单,其实他有他的设计思路)。不过比手写fmt. Printxxx还是强很多的。至少在输出的位置做了线程安全的保护。其官方手册见Golang log (天朝的墙大家懂的)。这里给出一个简单使用的例子:

1
2
3
4
5
6
7
package main
import (
    "log"
)
func main(){
    log.Fatal("Come with fatal,exit with 1 \n")
}

编译运行后,会看到程序打印了 Come with fatal,exit with 1 然后就退出了,如果用 echo $? 查看退出码,会发现是 “1”。

一般接口

Golang's log模块主要提供了3类接口。分别是 “Print 、Panic 、Fatal ”。当然是用前先包含log包。

1
2
3
import(
    "log"
)

为了方便是用,Golang和Python一样,在提供接口时,提供一个简单的包级别的使用接口。不同于Python,其输出默认定位到标准错误 可以通过SetOutput 进行修改。

对每一类接口其提供了3中调用方式,分别是 "Xxxx 、 Xxxxln 、Xxxxf" 比如对于Print就有:

1
2
3
log.Print
log.Printf
log.Println
  • log.Print :表示其参数的调用方式和 fmt.Print 是类似的,即输出对象而不用给定特别的标志符号。

  • log.Printf : 表示其参数的调用方式和 fmt.Printf 是类似的,即可以用C系列的格式化标志表示输出对象的类型,具体类型表示 可以参考fmt.Printf的文档

  • log.Println: 表示其调用方式和fmt.Println 类似,其和log.Print基本一致,仅仅是在输出的时候多输出一个换行

这里是以 “Print”来具体说明的,对于“Panic”和“Fatal”也是一样的。下面再以"Print"为例,看下调用方式:

1
2
3
4
5
6
7
8
9
10
package main
import (
    "log"
)
func main(){
    arr := []int {2,3}
    log.Print("Print array ",arr,"\n")
    log.Println("Println array",arr)
    log.Printf("Printf array with item [%d,%d]\n",arr[0],arr[1])
}

会得到如下结果:

1
2
3
2014/05/02 12:27:19 Print array [2 3]
2014/05/02 12:27:19 Println array [2 3]
2014/05/02 12:27:19 Printf array with item [2,3]

输出中的日期和时间是默认的格式,如果直接调用简单接口,其格式是固定的,可以通过 SetFlags 方法进行修改,同时这里输出 内容的(传个log.Print的内容)前面和时间的后面是空的,这也是默认的行为,我们可以通过添加前缀来表示其是一条"Warnning" 或者是一条"Debug"日志。通过使用 SetPrefix 可以设置该前缀。

SetOutputSetFlagsSetPrefix 这里关系不大,先不解释,留到后面介绍Logger类型中一并解释。

看完了 log.PrintXxx 接口,我们再来看下 log.FatalXxx 接口,我们以 log.Fatal 为例介绍其功能。如最开始看到的例子, 在调用 log.Fatal 接口后,会先将日志内容打印到标准输出,接着调用系统的 os.exit(1) 接口,退出程序返回状态为 “1”

比较复杂的是 log.PanicXxx ,看该函数的说明,其相当于再把日志内容刷到标准错误后调用 panic 函数(不清楚Golan的defer-recover-panic机制可以Golang Blog去学习一下)。这里举个常用的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
import (
    "log"
    "fmt"
)
func main(){
    defer func(){
        if e:= recover();e!= nil {
            fmt.Println("Just comming recover")
            fmt.Println("e from recover is :",e)
            fmt.Println("After recover")
        }
    }()
    arr := []int {2,3}
    log.Panic("Print array ",arr,"\n")
}

结果为:

1
2
3
4
2014/05/03 13:52:42 Print array [2 3]
Just comming recover
e from recover is : Print array [2 3]
After recover

从结果我们可以看出,是先将日志刷入标准输出,然后通过defer里面的recover进行捕获panic的内容。

自定义Logger类型

理清了“Print 、Panic 、Fatal ”后我们就好介绍 log.Logger 类型了。该类型提供了一个New方法用来创建对象。

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

其初始化条件分别是日志写入的位置 out ,日志的前缀内容 prefix ,以及日志的内容flag。可以通过上面介绍的SetOutputSetFlagsSetPrefix 依次对其进行设置。

  • 输出位置out,是一个io.Writer对象,该对象可以是一个文件也可以是实现了该接口的对象。通常我们可以用这个来指定 其输出到哪个文件

  • prefix 我们在前面已经看到,就是在日志内容前面的内容。我们可以将其置为 "[Info]" 、 "[Warning]"等来帮助区分日志 级别。

  • flags 较为迷惑,其实际上就是一个选项,可选的值有:

1
2
3
4
5
6
Ldate         = 1 << iota     // the date: 2009/01/23 形如 2009/01/23 的日期
Ltime                         // the time: 01:23:23   形如 01:23:23   的时间
Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  形如01:23:23.123123   的时间
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 文件名和行号
LstdFlags     = Ldate | Ltime // 日期和时间

表示在日志内容开头,我们暂且称之为日志抬头,打印出相关内容。对于上面的默认格式就是 LstdFlags 打印出日期和时间。

该方法还定义了如上一些同名方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
func (l *Logger) Print(v ...interface{})
func (l *Logger) Printf(format string, v ...interface{})
func (l *Logger) Println(v ...interface{})
func (l *Logger) Fatal(v ...interface{})
func (l *Logger) Fatalf(format string, v ...interface{})
func (l *Logger) Fatalln(v ...interface{})
func (l *Logger) Panic(v ...interface{})
func (l *Logger) Panicf(format string, v ...interface{})
func (l *Logger) Panicln(v ...interface{})
func (l *Logger) Flags() int
func (l *Logger) Prefix() string
func (l *Logger) SetFlags(flag int)
func (l *Logger) SetPrefix(prefix string)

其中 “Print 、Panic 、Fatal ” 系列函数和之前介绍的一样,Flags和Prefix分别可以获得log.Logger当前的日志抬头和前缀。 SetFlags ,SetPrefix 则可以用来设置日志抬头和前缀。

使用实例

最后我看有log模块将debug日志打印到文件的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import (
    "log"
    "os"
)
func main(){
    fileName := "xxx_debug.log"
    logFile,err  := os.Create(fileName)
    defer logFile.Close()
    if err != nil {
        log.Fatalln("open file error !")
    }
    debugLog := log.New(logFile,"[Debug]",log.Llongfile)
    debugLog.Println("A debug message here")
    debugLog.SetPrefix("[Info]")
    debugLog.Println("A Info Message here ")
    debugLog.SetFlags(debugLog.Flags() | log.LstdFlags)
    debugLog.Println("A different prefix")
}

运行后打开日志文件我们可以看到相应的日志内容

Golang 标准库提供的Log(一)的更多相关文章

  1. Golang 标准库log的实现

      原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...

  2. golang 标准库间依赖的可视化展示

    简介 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内 ...

  3. golang标准库分析之net/rpc

    net/rpc是golang提供的一个实现rpc的标准库.

  4. golang 标准库

    前言 不做文字搬运工,多做思路整理 就是为了能速览标准库,只整理我自己看过的...... 最好能看看英文的 标准库 fmt strconv string 跳转 golang知识库总结

  5. golang标准库 context的使用

    本文索引 问题引入 context包简介 示例 问题引入 goroutine为我们提供了轻量级的并发实现,作为golang最大的亮点之一更是备受推崇. goroutine的简单固然有利于我们的开发,但 ...

  6. Golang标准库——io-接口

    接口 Read相关 Reader Reader接口用于包装基本的读取方法. type Reader interface { //将数据读入到p中,直到读满p或者读取的过程中遇到错误,此时返回的n< ...

  7. Golang标准库——io-结构

    结构 LimitedReader 定义 限制从Reader中读取的字节数. type LimitedReader struct { R Reader // underlying reader N in ...

  8. golang 标准库 sync.Map 中 nil 和 expunge 区别

    本文不是 sync.Map 源码详细解读,而是聚焦 entry 的不同状态,特别是 nil 状态和 expunge 状态的区分. entry 是 sync.Map 存放值的结构体,其值有三种,分别为 ...

  9. golang标准库中有些函数只有签名没有函数体是怎么回事?

随机推荐

  1. sql中简单的触发器功能

    触发器分为DML触发器和DDL触发器DML触发器包含After触发器,执行insert update delete语句后会触发after触发器,会事务回滚DML触发器还包含instead of触发器, ...

  2. ecshop整合discuz教程完美教程

    所需软件: ecshop安装包:    ECShop_V2.7.3_UTF8_release1106.rarucenter安装包:   UCenter_1.6.0_SC_UTF8.zipdiscuz! ...

  3. Android程序中欢迎界面

    额,在做项目中,肯定首先要用到欢迎界面,下面是我在做项目中用的最简单的一个欢迎界面,即打开程序时,先是显示一张图片,然后等一段时间后图片消失,进入登录界面.直接上代码,有注释也不用解释了: 首先是We ...

  4. User control's property loses value after a postback

    User control's property loses value after a postback All variables (and controls) are disposed at th ...

  5. java 子类对象实例化的过程

    大家往往听说  子类继承了父类就有了父类中的所有的非私有的属性,但是怎么就有了父类的属性了呢 ?且听下面分解 子类对象实例化的过程: 1 从结果上来看:(继承性) 子类继承了父类以后 就获取了父类中声 ...

  6. 使用python实现希尔、计数、基数排序

    希尔排序 希尔排序是一个叫希尔的数学家提出的一种优化版本的插入排序. 首先取一个整数d1=n//2,将元素分为d1个组,每组相邻元素之间的距离为d1,在各组内进行直接插入排序. 取第二个整数d2=d1 ...

  7. java连SQLServer失败 java.lang.ClassNotFoundException:以及 javax.xml.bind.JAXBException

    总结:jdk1.8及以下连sqlserver只需驱动,1.8以上除了驱动还需JAXB API. 1       java连SQLServer必须要先下驱动.否则出现: java.lang.ClassN ...

  8. 洛谷 P1742 最小圆覆盖 (随机增量)

    题目链接:P1742 最小圆覆盖 题意 给出 N 个点,求最小的包含所有点的圆. 思路 随机增量 最小圆覆盖一般有两种做法:随机增量和模拟退火.随机增量的精确度更高,这里介绍随机增量的做法. 先将所有 ...

  9. 【题解】Tom的烦恼

    题目描述 Tom是一个非常有创业精神的人,由于大学学的是汽车制造专业,所以毕业后他用有限的资金开了一家汽车零件加工厂,专门为汽车制造商制造零件.由于资金有限,他只能先购买一台加工机器.现在他却遇到了麻 ...

  10. 【java】读写文件

    不要吐槽我为啥不写try,catch. 默认的相对路径是在工作空间的目录下. 如图 import java.io.*; import java.util.*; public class filerw ...