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. c语言蛋疼的字符串赋值

    我觉得c语言比较蛋疼的一个地方就是给字符串赋值,不是初始化,是赋值. char string[20]={0}; 你不能通过 string="hello";这种方式赋值.但是在字符串 ...

  2. dedecms图片上传函数

    /** * 图片上传类 * @param $file上传图片信息 * @param $ty */ function upload_pic($file, $ty) { if (!is_uploaded_ ...

  3. centos搭建本地yum源,

    比如将文件夹:/opt/mir/这个文件夹做成本地源: 1.在/etc/yum.repos.d/目录下新建一个.repo文件,比如mir-base.repo,在里面加入如下: [local]name= ...

  4. Shell 常用命令总结

      Shell常用命令总结 1  ls命令:列出文件 ls -la 列出当前目录下的所有文件和文件夹 ls a* 列出当前目录下所有以a字母开头的文件 ls -l *.txt 列出当前目录下所有后缀名 ...

  5. Jdom的简单操作

    http://blog.csdn.net/heirenheiren/article/details/7354108 http://www.cnblogs.com/hoojo/archive/2011/ ...

  6. swift学习之UITabelView ----使用xib定义cell

    // //  TwoViewController.swift //  tab // //  Created by su on 15/12/7. //  Copyright © 2015年 tian. ...

  7. 团体程序设计天梯赛L2-001 紧急救援 2017-03-22 17:25 93人阅读 评论(0) 收藏

    L2-001. 紧急救援 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国 ...

  8. java中时间

    格式转化 SimpleDateFormat package day1211.common; import java.sql.Date;import java.sql.Timestamp;import ...

  9. 用 pyqt4 编写的一个翻译小工具

    有时候我们在开发时遇到一些陌生的英文单词或者不容易看出某些长句的中文意思时该怎么办呢?打开桌面上的翻译软件?打开浏览器里收藏着的翻译网址或者直接贴上百度的搜索框去查?这些方法固然可以,还很常见,但如果 ...

  10. visual studio code中使用emmet插件在.vue文件失效

    使用visual studio code编辑.vue文件时,emmet插件无法使用,可以通过以下两种试解决: 1.文件→设置,在右侧窗口添加以下代码: "emmet.syntaxProfil ...