Golang 标准库提供的Log(一)
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
可以设置该前缀。
SetOutput
SetFlags
SetPrefix
这里关系不大,先不解释,留到后面介绍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。可以通过上面介绍的SetOutput
SetFlags
SetPrefix
依次对其进行设置。
输出位置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(一)的更多相关文章
- Golang 标准库log的实现
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...
- golang 标准库间依赖的可视化展示
简介 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内 ...
- golang标准库分析之net/rpc
net/rpc是golang提供的一个实现rpc的标准库.
- golang 标准库
前言 不做文字搬运工,多做思路整理 就是为了能速览标准库,只整理我自己看过的...... 最好能看看英文的 标准库 fmt strconv string 跳转 golang知识库总结
- golang标准库 context的使用
本文索引 问题引入 context包简介 示例 问题引入 goroutine为我们提供了轻量级的并发实现,作为golang最大的亮点之一更是备受推崇. goroutine的简单固然有利于我们的开发,但 ...
- Golang标准库——io-接口
接口 Read相关 Reader Reader接口用于包装基本的读取方法. type Reader interface { //将数据读入到p中,直到读满p或者读取的过程中遇到错误,此时返回的n< ...
- Golang标准库——io-结构
结构 LimitedReader 定义 限制从Reader中读取的字节数. type LimitedReader struct { R Reader // underlying reader N in ...
- golang 标准库 sync.Map 中 nil 和 expunge 区别
本文不是 sync.Map 源码详细解读,而是聚焦 entry 的不同状态,特别是 nil 状态和 expunge 状态的区分. entry 是 sync.Map 存放值的结构体,其值有三种,分别为 ...
- golang标准库中有些函数只有签名没有函数体是怎么回事?
随机推荐
- 第六周-Scrum Meeting
第一部分ScrumMeeting 每个人的工作: 成员 任务 ISSUE链接 本周已完成的工作 本周计划完成的工作 工作中遇到的困难 李卓峻 负责商品信息页面的界面设计与功能实现 https://gi ...
- 生成函数小结——[ EGF ][ ln 的一个套路 ][ 概率生成函数 ]
看了jcvb的WC2015交流课件.虽然没懂后面的复合逆部分,但生成函数感觉受益良多. 指数生成函数 集合中大小为 i 的对象的权值是 \( a_i \) ,该集合的生成函数是 \( \sum\lim ...
- [CSP-S模拟测试]:字符(模拟+剪枝)
题目传送门(内部题33) 输入格式 第一行,两个整数$T,C$,表示测试数据组数和字符种类数.对于每组数据:第一行,一个正整数$M$:接下来的$M$行,每行两个整数$P_k,X_k$($S$的下标从$ ...
- inline-block空隙怎么解决
方法一:移除空格 元素间留白间距出现的原因就是标签段之间的空格,因此,去掉HTML中的空格,自然间距就木有了.考虑到代码可读性,显然连成一行的写法是不可取的,我们可以: <div class=& ...
- NetworkComms V3 序列化器之Protobuf.net和 JSONSerializer
NetworkComms v3版本中,默认使用的是protobuf.net序列化器. 即当您没有指定序列化的时候,系统自动使用默认的protobuf.net序列化器. 当然我们也可以自己指定序列化器 ...
- 用processing生成屏保程序
想法 利用随机数控制圆圈的大小.位置以及颜色,可以产生随机的美感. 让小球动起来,并且在屏幕边界处产生反弹效果. 代码 1: float circle_x = (float) 0.0; 2: floa ...
- 如何深入理解Java泛型
一.泛型的作用与定义 1.1泛型的作用 使用泛型能写出更加灵活通用的代码泛型的设计主要参照了C++的模板,旨在能让人写出更加通用化,更加灵活的代码.模板/泛型代码,就好像做雕塑时的模板,有了模板,需要 ...
- 分布式-技术专区-Redis和MySQL缓存一致性问题
1.Redis 缓存和 MySQL 数据如何实现一致性 需求起因 缓存和数据库一致性解决方案 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节.所以,就需要使用redis做一个缓冲操 ...
- CentOS 7 安装 nginx1.15
1,安装依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel SSL功能需要openssl库 gzip模块需要z ...
- docker部署一个简单的mian.py项目文件
安装docker yum install -y docker 启动docker systemctl start docker 查询可安装的Python版本,默认centos python 2.7 ...