在 Go 语言中使用 Log 包--转自GCTT
Linux 在许多方面相对于 Windows 来说都是独特的,在 Linux 中编写程序也不例外。标准输出,标准 err 和 null devices 的使用不仅是一个好主意,也是一个原则。如果您的程序将记录日志信息,则最好遵循目标约定。这样,您的程序将兼容所有 Mac/Linux 工具和托管环境。
Go 在标准库中有一个 log 包和 logger 类型。使用 log 包将为您提供成为优秀公民 (译注:指 log 包兼容性非常好) 所需的一切。您将能够写入所有标准设备,自定义文件或支持 io.Writer 接口的任何目标。
我提供了一个非常简单的示例,它将帮助您开始使用 logger :
package main import (
"io"
"io/ioutil"
"log"
"os"
) var (
Trace *log.Logger
Info *log.Logger
Warning *log.Logger
Error *log.Logger
) func Init(
traceHandle io.Writer,
infoHandle io.Writer,
warningHandle io.Writer,
errorHandle io.Writer) { Trace = log.New(traceHandle,
"TRACE: ",
log.Ldate|log.Ltime|log.Lshortfile) Info = log.New(infoHandle,
"INFO: ",
log.Ldate|log.Ltime|log.Lshortfile) Warning = log.New(warningHandle,
"WARNING: ",
log.Ldate|log.Ltime|log.Lshortfile) Error = log.New(errorHandle,
"ERROR: ",
log.Ldate|log.Ltime|log.Lshortfile)
} func main() {
Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr) Trace.Println("I have something standard to say")
Info.Println("Special Information")
Warning.Println("There is something you need to know about")
Error.Println("Something has failed")
}
运行此程序时,您将获得以下输出:
INFO: // :: main.go:: Special Information
WARNING: // :: main.go:: There is something you need to know about
ERROR: // :: main.go:: Something has failed
您会注意到没有显示 Trace logging (译注:跟踪记录器)。让我们看看代码,找出原因。
查看 Trace logging 部分的代码:
var Trace *log.Logger Trace = log.New(traceHandle,
"TRACE: ",
log.Ldate|log.Ltime|log.Lshortfile) Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr) Trace.Println("I have something standard to say")
该代码创建一个名为 Trace 的包级变量,它是一个指向 log.Logger 对象的指针。然后在 Init 函数内部创建一个新的 log.Logger 对象。log.New 函数的参数如下:
func New(out io.Writer, prefix string, flag int) *Logger
out: The out variable sets the destination to which log data will be written. // 译注 out 变量设置将写入日志数据的目标
prefix: The prefix appears at the beginning of each generated log line. // 译注 前缀出现在每个生成的日志行的开头。
flags: The flag argument defines the logging properties. // 译注 flag 参数定义日志记录属性
Flags: const (
// Bits or’ed together to control what’s printed. There is no control over the
// order they appear (the order listed here) or the format they present (as
// described in the comments). A colon appears after these items:
// 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
Ldate = << iota // the date: 2009/01/23
Ltime // the time: 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
LstdFlags = Ldate | Ltime // initial values for the standard logger
)
在此示例程序中,Trace 的目标是 ioutil.Discard 。这是一个 null device (译注:对应 /dev/null 相当于垃圾桶,消息直接丢弃),所有写入调用都可以成功而不做任何事情。因此,使用 Trace 写入时,终端窗口中不会显示任何内容。
再来看看 Info 的代码:
var Info *log.Logger Info = log.New(infoHandle,
"INFO: ",
log.Ldate|log.Ltime|log.Lshortfile) Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr) Info.Println("Special Information")
对于 Info (译注:消息记录器),os.Stdout 传入到 init 函数给了 infoHandle 。这意味着当您使用 Info 写消息时,消息将通过标准输出显示在终端窗口中。
最后,看下 Error 的代码:
var Error *log.Logger Error = log.New(errorHandle,
"ERROR: ", // 译注: 原文是 INFO 与原始定义不同,应该是笔误,故直接修改
log.Ldate|log.Ltime|log.Lshortfile) Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr) Error.Println("Something has failed") // 译注: 原文是 Special Information 与原始定义不同,应该是笔误,故直接修改
这次 os.Stderr 传入到 Init 函数给了 errorHandle 。这意味着当您使用 Error 写消息时,该消息将通过标准错误显示在终端窗口中。但是,将这些消息传递给 os.Stderr 允许运行程序的其他应用程序知道发生了错误。
由于支持 io.Writer 接口的任何目标都可以接受,因此您可以创建和使用文件:
file, err := os.OpenFile("file.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, )
if err != nil {
log.Fatalln("Failed to open log file", output, ":", err)
}
MyFile = log.New(file,
"PREFIX: ",
log.Ldate|log.Ltime|log.Lshortfile)
在示例代码中,打开一个文件,然后将其传递给 log.New 函数。现在,当您使用 MyFile 进行写入时,数据将写到 file.txt 里。
您还可以让 logger (译注:记录器) 同时写入多个目标。
file, err := os.OpenFile("file.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, )
if err != nil {
log.Fatalln("Failed to open log file", output, ":", err)
}
multi := io.MultiWriter(file, os.Stdout)
MyFile := log.New(multi,
"PREFIX: ",
log.Ldate|log.Ltime|log.Lshortfile)
这里数据将写入到文件和标准输出里。
注意在处理 OpenFile 的任何错误时使用 log.Fatalln 方法。 log 包提供了一个可以配置的初始 logger。以下是使用具有标准配置的日志的示例程序:
package main import (
"log"
) func main() {
log.Println("Hello World")
}
以下是输出:
2013/11/05 18:42:26 Hello World
如果想要删除或更改输出格式,可以使用 log.SetFlags 方法:
package main import (
"log"
) func main() {
log.SetFlags()
log.Println("Hello World")
}
以下是输出:
Hello World
现在所有格式都已删除。如果要将输出发送到其他目标,请使用 log.SetOutput :
package main import (
"io/ioutil"
"log"
) func main() {
log.SetOutput(ioutil.Discard)
log.Println("Hello World")
}
现在终端窗口上不会显示任何内容。您可以使用任何支持io.Writer 接口的目标。
基于这个例子,我为我的所有程序编写了一个新的日志包:
go get github.com/goinggo/tracelog
我希望在开始编写Go程序时我就知道 log 和 loggers 。期待将来能够看到我写的更多日志包。
via: https://www.ardanlabs.com/blog/2013/11/using-log-package-in-go.html
作者:William Kennedy 译者:chaoshong 校对:polaris1119
在 Go 语言中使用 Log 包--转自GCTT的更多相关文章
- R语言中的数据处理包dplyr、tidyr笔记
R语言中的数据处理包dplyr.tidyr笔记 dplyr包是Hadley Wickham的新作,主要用于数据清洗和整理,该包专注dataframe数据格式,从而大幅提高了数据处理速度,并且提供了 ...
- R语言中的机器学习包
R语言中的机器学习包 Machine Learning & Statistical Learning (机器学习 & 统计学习) 网址:http://cran.r-project ...
- 在Go语言中记录log:seelog包
前两周调bug调的吐血,虽然解决了但是还是挺浪费时间的.跟同事聊了聊,觉得我们现在项目中的日志记录太少了,导致出了问题不知道怎么下手,还得自己改代码记录日志,然后排查问题.这样如果将来还有bug的话还 ...
- go 语言中常用的包
来自学习go语言.pdf 译者刑星 ==== fmt 包fmt实现了格式化IO函数,这与c的printf和scanf类似,格式化短语派生于c %v 默认格式的值.当打印结构时,加号(%+v)会增加字段 ...
- r语言,安装外部包 警告: 无法将临时安装
安装R语言中的外部包时,出现错误提示 试开URL’https://mirrors.tuna.tsinghua.edu.cn/CRAN/bin/windows/contrib/3.3/ggplot2_2 ...
- Go语言中的并发编程
并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天) ...
- go标准库-log包源码学习
log包是go语言提供的一个简单的日志记录功能,其中定义了一个结构体类型 Logger,是整个包的基础部分,包中的其他方法都是围绕这整个结构体创建的. Logger结构 Logger结构的定义如下: ...
- 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测
如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...
- node.js中模块和包
node.js中模块和包 什么是模块 如何创建并加载模块 1. 创建模块 2. 单次加载 3. 覆盖 exports 如何创建一个包 1. 作为文件夹的模块 2. package.json 如何使用包 ...
随机推荐
- Ubuntu 17 Nginx 配置 laravel 运行环境
1 安装 nginx #aptitude install nginx #apatitude install php7.1-fpm 2 在 /etc/nginx/sites-available 建立 s ...
- (转)【经验之谈】Git使用之TortoiseGit配置VS详解
原文地址:http://www.cnblogs.com/xishuai/p/3590705.html 前言 上一篇<[经验之谈]Git使用之Windows环境下配置>: 安装 配置和使用 ...
- 转:css实现强制不换行/自动换行/强制换行
css实现强制不换行/自动换行/强制换行 [日期:2007-08-22] 来源: 作者: [字体:大 中 小] 强制不换行 div{ white-space:nowrap;} 自动换行 div{ ...
- [label][JavaScript][The Defined Guide of JavaScript] 变量的作用域
变量的作用域 一个变量的作用域(scope)是程序中定义这个变量的区域. 全局(global)变量的作用域(scope)是全局性的,即在JavaScript代码中,它处处都有定义. 而在函数之内 ...
- 咏南BS开发框架
咏南BS开发框架 开发工具为:DELPHI 2006及以上版本.欢迎索取演示. 通用的三级权限管理. 登录验证 输入帐号和密码验证登录系统. 功能菜单 在这里设置好菜单,系统运行的时候会根据菜单设置动 ...
- SQL Server触发器的基本使用
sqlserver_SQL触发器的使用及语法(转自:百度文库) 定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序.触发器是一个特殊的存储过程 ...
- Android-封装JSON数据(JSON对象/JSON数组)
Android-封装JSON数据(JSON对象/JSON数组),一般情况下不会在Android端封装JSON的数据,因为封装JSON的数据是在服务器端进行封装了,Android更多的工作是解析(JSO ...
- Android-自定义侧滑菜单
效果图: 需要继承ViewGroup,因为包含了子控件,菜单子控件 与 主页面子控件 Activity Xml布局相关: <!-- 自定义侧滑菜单 SlideMenu --> <Li ...
- 注册一个GitHub用户的过程
今天,我注册了一个GitHub用户.一开始,不知道GitHub是什么,还以为叫什么"getup",心里还想着什么网站名字这么奇怪,后来在舍友的帮助之下知道了原来是叫GitHub.下 ...
- MD5签名
/// <summary> /// 校验签名 /// </summary> /// <param name="mode ...