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

本文由 GCTT 原创编译,Go语言中文网 荣誉推出

在 Go 语言中使用 Log 包--转自GCTT的更多相关文章

  1. R语言中的数据处理包dplyr、tidyr笔记

    R语言中的数据处理包dplyr.tidyr笔记   dplyr包是Hadley Wickham的新作,主要用于数据清洗和整理,该包专注dataframe数据格式,从而大幅提高了数据处理速度,并且提供了 ...

  2. R语言中的机器学习包

    R语言中的机器学习包   Machine Learning & Statistical Learning (机器学习 & 统计学习)  网址:http://cran.r-project ...

  3. 在Go语言中记录log:seelog包

    前两周调bug调的吐血,虽然解决了但是还是挺浪费时间的.跟同事聊了聊,觉得我们现在项目中的日志记录太少了,导致出了问题不知道怎么下手,还得自己改代码记录日志,然后排查问题.这样如果将来还有bug的话还 ...

  4. go 语言中常用的包

    来自学习go语言.pdf 译者刑星 ==== fmt 包fmt实现了格式化IO函数,这与c的printf和scanf类似,格式化短语派生于c %v 默认格式的值.当打印结构时,加号(%+v)会增加字段 ...

  5. r语言,安装外部包 警告: 无法将临时安装

    安装R语言中的外部包时,出现错误提示 试开URL’https://mirrors.tuna.tsinghua.edu.cn/CRAN/bin/windows/contrib/3.3/ggplot2_2 ...

  6. Go语言中的并发编程

    并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天) ...

  7. go标准库-log包源码学习

    log包是go语言提供的一个简单的日志记录功能,其中定义了一个结构体类型 Logger,是整个包的基础部分,包中的其他方法都是围绕这整个结构体创建的. Logger结构 Logger结构的定义如下: ...

  8. 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测

    如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...

  9. node.js中模块和包

    node.js中模块和包 什么是模块 如何创建并加载模块 1. 创建模块 2. 单次加载 3. 覆盖 exports 如何创建一个包 1. 作为文件夹的模块 2. package.json 如何使用包 ...

随机推荐

  1. 在Linux(Ubuntu)下安装Arial、Times New Roman等字体

    在Linux下做文档.作图的时候,可能需要用到Arial和Times New Roman等字体.但是由于版权问题,Linux一般是不直接提供这些字体的. 注意字体也是有版权的!不过有版权也不代表一定会 ...

  2. Caffe 议事(一):从零开始搭建 ResNet 之 残差网络结构介绍和数据准备

    声明:Caffe 系列文章是我们实验室 黄佳斌 大神所写的内部学习文档,已经获得他的授权允许. 本参考资料是在 Ubuntu14.04 版本下进行,并且默认 Caffe 所需的环境已经配置好,下面教大 ...

  3. appium镜像设置

    npm --registry http://registry.cnpmjs.org install -g appium 使用npm的国内镜像可以安装,速度很不错. 以后不想输入ip的话可以输入以下命令 ...

  4. java MD5 并发

    Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321(R.Rives ...

  5. PHP(七)函数

  6. UIPickerView 修改必须滚动才修改值的bug

    //相应的选择转动 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSI ...

  7. Google Tango service outdated谷歌Tango的服务过时了

    If you device showed "tango service outdated." It means that your Tango Core need to be up ...

  8. Scala程序编译运行

    1.编译 Scala演示代码如下: <pre name="code" class="plain">/** * @author Administrat ...

  9. 洛谷P1486 [NOI2004]郁闷的出纳员(splay)

    题目描述 OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资 ...

  10. delphi 10.1 berlin datasnap提交clientdataset.delta报:invalid variant type conversion(类型转换错误)问题的解决

    delphi 10.1 berlin datasnap提交clientdataset.delta报:invalid variant type conversion(类型转换错误)问题的解决,需要打这个 ...