Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Golang中log日志包的使用

Golang中log日志包的使用

作者头像
Java架构师必看
发布于 2021-09-14 06:53:06
发布于 2021-09-14 06:53:06
86000
代码可运行
举报
文章被收录于专栏:Java架构师必看Java架构师必看
运行总次数:0
代码可运行

Golang中log日志包的使用

强烈推介IDEA2020.2破解激活,IntelliJ IDEA 注册码,2020.2 IDEA 激活码

文章目录

1.前言

作为后端开发人员,日志文件记录了发生在操作系统或其他软件运行时的事件或状态。技术人员可以通过日志记录进而判断系统的运行状态,寻找导致系统出错、崩溃的成因等。这是我们分析程序问题常用的手段。

2.log包介绍

在Golang中记录日志非常方便,Golang提供了一个简单的日志记录包log,包中定义了一个结构体类型 Logger,是整个包的基础部分,包中的其他方法都是围绕这整个结构体创建的。

Logger结构体

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// A Logger represents an active logging object that generates lines of
// output to an io.Writer. Each logging operation makes a single call to
// the Writer's Write method. A Logger can be used simultaneously from
// multiple goroutines; it guarantees to serialize access to the Writer.
type Logger struct {
   
	mu     sync.Mutex // ensures atomic writes; protects the following fields
	prefix string     // prefix on each line to identify the logger (but see Lmsgprefix)
	flag   int        // properties
	out    io.Writer  // destination for output
	buf    []byte     // for accumulating text to write
}

该结构体表示一个日志对象,通过io.Writer进行日志输出,每次记录都简单地调用io.Writerwrite方法。一个Logger可以被多个goroutines同步执行。对各个成员含义解析:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mu :是sync.Mutex,它是一个同步互斥锁,用于保证日志记录的原子性.
prefix :是输入的日志每一行的前缀
flag :是一个标志,用于设置日志的打印格式
out :日志的输出目标,需要是一个实现了 io.Writer接口的对象,如: os.Stdout, os.Stderr, os.File等等
buf :用于缓存数据

flag可选值

其中flag的值在log包中定义了一些常量,它的作用主要是用于标识日志信息附加携带的信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// These flags define which text to prefix to each log entry generated by the Logger.
// Bits are or'ed together to control what's printed.
// With the exception of the Lmsgprefix flag, there is no
// control over the order they appear (the order listed here)
// or the format they present (as described in the comments).
// The prefix is followed by a colon only when Llongfile or Lshortfile
// is specified.
// For example, flags Ldate | Ltime (or LstdFlags) produce,
// 2009/01/23 01:23:23 message
// while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
// 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
const (
	Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23
	Ltime                         // the time in the local time zone: 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
	LUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zone
	Lmsgprefix                    // move the "prefix" from the beginning of the line to before the message
	LstdFlags     = Ldate | Ltime // initial values for the standard logger
)

如可以指定日期、时间、毫秒时间、绝对路径和行号、文件名和行号等,LstdFlags为默认的flag,只同时携带了日期和时间两个信息。

3.log包的使用

3.1 日志输出方法

log包中定义了如下的一套日志信息输出方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func (l *Logger) Print(v ...interface{
   }) //直接打印输出
func (l *Logger) Fatal(v ...interface{
   }) //输出日志后立即结束程序
func (l *Logger) Panic(v ...interface{
   }) //输出日志后抛出异常

和这三个方法相似的另外的方法都很好理解,就是换行或者格式化输出。

3.2 自定义创建日志对象

log包定义了一个New方法,并通过默认flag初始化了一个全局的私有logger:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// New creates a new Logger. The out variable sets the
// destination to which log data will be written.
// The prefix appears at the beginning of each generated log line, or
// after the log header if the Lmsgprefix flag is provided.
// The flag argument defines the logging properties.
func New(out io.Writer, prefix string, flag int) *Logger {
   
	return &Logger{
   out: out, prefix: prefix, flag: flag}
}

var std = New(os.Stderr, "", LstdFlags)

如果你刚好只需要日期和时间这两个额外的信息,就可以直接通过log包名调用方法,默认就是使用的这个初始化的std结构体的对应方法,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
log.Println("hello,world~")

如果默认提供的日志配置不能满足您的需求,我们就可以自己去主动调用这个New方法,配置创建我们自己的logger。该方法所需的三个参数,描述如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
out io.Writer:表示输出位置,可选值如 os.Stdout 为系统控制台,os.OpenFile 输出到单独的文件
prefix string: 表示统一前缀,会添加到生成的每一条日志前面,如debug的场景我们可以单独使用一个为[DEBUG]的前缀
flag int:表示额外信息标识,上文介绍过

当然,我们也可以单独调用如下相关的方法来单独设置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func (l *Logger) SetOutput(w io.Writer)
func (l *Logger) SetFlags(flag int)
func (l *Logger) SetPrefix(prefix string)

3.3 封装自定义日志包

到这里,聪明的小伙伴一定有些思路根据自己的应用场景,基于官方的log包,封装出自己的log日志包了~ 如下提供一个示例,具体还请自行优化代码结构:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package logger

import (
	"io"
	"log"
	"os"
)

const (
	flag           = log.Ldate | log.Ltime | log.Lshortfile
	preDebug       = "[DEBUG]"
	preInfo        = "[INFO]"
	preWarning     = "[WARNING]"
	preError       = "[ERROR]"
)

var (
	logFile       io.Writer
	debugLogger   *log.Logger
	infoLogger    *log.Logger
	warningLogger *log.Logger
	errorLogger   *log.Logger
	defaultLogFile = "/var/log/web.log"
)

func init() {
   
	var err error
	logFile, err = os.OpenFile(defaultLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
	if err != nil {
   
		defaultLogFile = "./web.log"
		logFile, err = os.OpenFile(defaultLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
		if err != nil {
   
			log.Fatalf("create log file err %+v", err)
		}
	}
	debugLogger = log.New(logFile, preDebug, flag)
	infoLogger = log.New(logFile, preInfo, flag)
	warningLogger = log.New(logFile, preWarning, flag)
	errorLogger = log.New(logFile, preError, flag)
}

func Debugf(format string, v ...interface{
   }) {
   
	debugLogger.Printf(format, v...)
}

func Infof(format string, v ...interface{
   }) {
   
	infoLogger.Printf(format, v...)
}

func Warningf(format string, v ...interface{
   }) {
   
	warningLogger.Printf(format, v...)
}

func Errorf(format string, v ...interface{
   }) {
   
	errorLogger.Printf(format, v...)
}

func SetOutputPath(path string) {
   
	var err error
	logFile, err = os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
	if err != nil {
   
		log.Fatalf("create log file err %+v", err)
	}
	debugLogger.SetOutput(logFile)
	infoLogger.SetOutput(logFile)
	warningLogger.SetOutput(logFile)
	errorLogger.SetOutput(logFile)
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "yourPath/logger"

func main() {
   
	author := "korbin"
	logger.Debugf("hello,%s",author)
	logger.Infof("hello,%s",author)
	logger.Warningf("hello,%s",author)
	logger.Errorf("hello,%s",author)
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DEBUG]2020/12/01 11:33:07 logger.go:43: hello,korbin
[INFO]2020/12/01 11:33:07 logger.go:47: hello,korbin
[WARNING]2020/12/01 11:33:07 logger.go:51: hello,korbin
[ERROR]2020/12/01 11:33:07 logger.go:55: hello,korbin

如该示例中的输出文件路径可以改为通过从配置文件读取或者通过命令行参数等,或者输出方式改为os.Stderr控制台等都行,根据自行情况而定。

3.4 log包进一步解析

另外其实我们也很容易发现,Logger结构体的日志输出方法,都是通过调用func (l *Logger) Output(calldepth int, s string) error方法实现的,在 Output 方法中,做了如下这些事情:

  1. 获取当前事件
  2. 对 Logger实例进行加锁操作
  3. 判断Logger的标志位是否包含 Lshortfile 或 Llongfile, 如果包含进入步骤4, 如果不包含进入步骤5
  4. 获取当前函数调用所在的文件和行号信息
  5. 格式化数据,并将数据写入到 l.out 中,完成输出
  6. 解锁操作

log包整体结构还是很简单的,有兴趣的小伙伴可以再自己多看一下源码。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Golang 语言的标准库 log 包怎么使用?
Golang 语言的标准库中提供了一个简单的 log 日志包,它不仅提供了很多函数,还定义了一个包含很多方法的类型 Logger。但是它也有缺点,比如不支持区分日志级别,不支持日志文件切割等。
frank.
2021/02/07
5300
关于log日志的深入学习笔记
什么是日志,简单来说就是记录,在程序中日志担任着重要的作用,利用日志信息,我们可以很轻易发现程序的运行状况,一个输出格式化很好的也可以很轻易的进行数据分析。那么Golang中对日志怎么操作呢?
陌无崖
2019/08/16
7140
关于log日志的深入学习笔记
GO的日志怎么玩
要是想了解如上问题的答案,欢迎查看文章 GO的定时器Timer 和定时任务cron
阿兵云原生
2023/02/16
5240
Go语言实战笔记(十八)| Go log 日志
在我们开发程序后,如果有一些问题需要对程序进行调试的时候,日志是必不可少的,这是我们分析程序问题常用的手段。
飞雪无情
2018/08/28
1.1K0
Go Log包使用
log包定义了Logger类型,该类型提供了一些格式化输出的方法。本包也提供了一个预定义的“标准”logger,可以通过调用函数Print系列(Print|Printf|Println)、Fatal系列(Fatal|Fatalf|Fatalln)、和Panic系列(Panic|Panicf|Panicln)来使用,比自行创建一个logger对象更容易使用。
王小明_HIT
2021/03/11
6320
一文搞懂Go语言标准库,log
Go 语言的标准库中提供了一个简单的 log 日志包,它不仅提供了很多函数,还定义了一个包含很多方法的类型 Logger。Logger 会打印每条日志信息的日期、时间,默认输出到标准错误。Fatal 系列函数会在写入日志信息后调用 os.Exit(1)。Panic 系列函数会在写入日志信息后 panic。下面详细介绍下标准库log的基本使用。
微客鸟窝
2021/12/27
4840
一文搞懂Go语言标准库,log
聊聊golang的log
序 本文主要研究一下golang的log OIP (98).jpeg log flags const ( Ldate = 1 << iota // the date in the local time zone: 2009/01/23 Ltime // the time in the local time zone: 01:23:23 Lmicroseconds // micr
code4it
2020/12/04
2950
聊聊golang的log
Go:log库的全面指南与使用技巧
在Go语言的标准库中,log包提供了简单而强大的日志功能。日志记录是软件开发中不可或缺的一部分,它不仅帮助开发人员调试和排查问题,还在系统运行中提供了宝贵的运行时信息。本文将详细讲解Go语言log库的各种功能及其使用技巧,帮助开发者更好地掌握和应用这一重要工具。
运维开发王义杰
2024/05/29
1K1
Go:log库的全面指南与使用技巧
Go每日一库之9:log
在日常开发中,日志是必不可少的功能。虽然有时可以用fmt库输出一些信息,但是灵活性不够。Go 标准库提供了一个日志库log。本文介绍log库的使用。
luckpunk
2023/09/15
3100
Golang学习笔记之日志log、zap
(1)Golang's log模块主要提供了3类接口。分别是 “Print 、Panic 、Fatal ”,对每一类接口其提供了3中调用方式,分别是 "Xxxx 、Xxxxln 、Xxxxf",基本和fmt中的相关函数类似。
李海彬
2018/12/29
2.3K0
Go语言日志
一、日志简介 使用开发工具时,控制台打印的信息就是日志信息 项目最终发布后是没有开发工具的,而需要记录日志应该把信息输出到文件中,这个功能也是日志的功能 在Go语言标准的log包提供了对日志的支持 有三种级别日志输出 Print() 输出日志信息 Panic() 打印日志信息,并触发panic,日志信息为Panic信息 Fatal() 打印日志信息后调用os.Exit(1) 所有日志信息打印时都带有时间,且颜色为红色 每种级别日志打印都提供了三个函数 Println() Print() Printf() 日
IT工作者
2022/03/31
2480
Go:log库中的文件行号显示实现原理探讨
在Go语言的日志记录中,了解日志记录的来源(即具体的文件名和行号)是非常重要的,这有助于开发人员快速定位和解决问题。Go语言的log包通过使用Lshortfile和Llongfile标志,提供了显示日志记录所在文件及其行号的功能。本文将详细讲解log包中显示文件行号的实现原理,并剖析相关的源码。
运维开发王义杰
2024/05/29
3520
Go:log库中的文件行号显示实现原理探讨
go web: 2 封装日志包log
在web项目中,记日志是非常重要的。所以,我做的第一件事,就是向log包动手。 和Python相比,log包功能上逊色不少,但它给我们提供了基础的构架,让我们能自己稍微封装下。
超级大猪
2019/11/21
1.7K0
go原生log模块的简易封装
go的原生log模块,功能稍简单。比如不支持自定义输出级别。只有默认的三个可用。println,Fatal,Panic等
杨永贞
2020/08/04
8860
1.Go语言之标准库学习记录(1)
描述: 我们进行Go语言编程之中当遇到不熟悉的内置函数时, 可以采用go doc builtin [builtinFunName]查看go语言内置函数。
全栈工程师修炼指南
2022/09/29
1.1K0
1.Go语言之标准库学习记录(1)
golang log日志
最近在做项目的时候发现beego的log系统挺好用,但是好用归好用,还不够舒服。希望能够自定义
老脸一红
2018/05/28
7721
Go的日志库log竟然这么简单!
最近在尝试阅读字节开源RPC框架Kitex的源码,看到日志库klog部分,果不其然在Go原生的log库的基础上增加了自己的设计,大体包括增加了一些格式化的输出、增加一些常用的日志级别等。
白泽z
2022/08/18
6220
Go的日志库log竟然这么简单!
从零实现ORM框架GeoORM-database/sql基础-01
本系列源码: https://gitee.com/DaHuYuXiXi/geo-orm
大忽悠爱学习
2022/09/27
5010
从零实现ORM框架GeoORM-database/sql基础-01
剖析Go编写的Socket服务器模块解耦及基础模块的设计
Server的解耦—通过Router+Controller实现逻辑分发 在实际的系统项目工程中中,我们在写代码的时候要尽量避免不必要的耦合,否则你以后在更新和维护代码的时候会发现如同深陷泥潭,随便改点东西整个系统都要变动的酸爽会让你深切后悔自己当初为什么非要把东西都写到一块去(我不会说我刚实习的时候就是这么干的。。。) 所以这一篇主要说说如何设计Sever的内部逻辑,将Server处理Client发送信息的这部分逻辑与Sevrer处理Socket连接的逻辑进行解耦~ 这一块的实现灵感主要是在读一个HTTP开
李海彬
2018/03/22
1.1K0
剖析Go编写的Socket服务器模块解耦及基础模块的设计
Go程序例子(76):日志记录
Go 标准库提供了简单的工具来从 Go 程序中输出日志,其中 log 包用于自由格式的输出,而 log/slog 包用于结构化输出。
用户11078756
2025/01/20
720
Go程序例子(76):日志记录
相关推荐
Golang 语言的标准库 log 包怎么使用?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验