Go中log包异或组合配置妙用详解

log 中的这种用法,你一定见过:

log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)

没见过的,自我反省下(逃

在 Go 语言的 log 包中,使用“位运算相或” (|) 来配置日志的 flag,是为了让我们灵活地组合多种日志信息输出选项。,比如是否显示日期、时间、微秒、文件名、行号等。

接下来详细解释这种方法的好处和原理。

1. 什么是 log 包中的 flag

log 包中,flag 是用来控制日志输出格式的一些选项。

每种 flag 都是一个二进制位掩码,通过不同的掩码组合,可以控制日志的显示内容。

这些 flag 选项定义如下:

const (
    Ldate         = 1 << iota     // 日期:2009/01/23
    Ltime                         // 时间:01:23:23
    Lmicroseconds                 // 微秒级时间:01:23:23.123123(需要同时有 Ltime)
    Llongfile                     // 完整文件名和行号:/a/b/c/d.go:23
    Lshortfile                    // 文件名和行号:d.go:23(会覆盖 Llongfile)
    LUTC                          // 使用 UTC 时间而非本地时间
    Lmsgprefix                    // 将“前缀”从行首移动到消息之前
    LstdFlags     = Ldate | Ltime // 默认值
)

这些常量是通过位移运算 1 << iota 定义的,保证每个 flag 只占用一位,且是唯一的。

这样一来,我们可以用按位或操作 | 来组合多个选项。

对应的值如下:

const (
	Ldate=1 << iota// iota =0,值为 1 << 0 = 1,二进制:00000001,相当于2的0次方
	Ltime          // iota = 1,值为 1 << 1 = 2,二进制:00000010,相当于2的1次方
	Lmicroseconds  // iota = 2,值为 1 << 2 = 4,二进制:00000100,相当于2的2次方
	Llongfile      // iota = 3,值为 1 << 3 = 8,二进制:00001000,相当于2的3次方
	Lshortfile     // iota = 4,值为 1 << 4 = 16,二进制:00010000,相当于2的4次方
	LUTC           // iota = 5,值为 1 << 5 = 32,二进制:00100000,相当于2的5次方
	Lmsgprefix     // iota = 6,值为 1 << 6 = 64,二进制:01000000,相当于2的6次方
)

2. 为什么使用按位或 (|) 来组合 flag

按位或 (|) 的好处是可以任意组合选项。因为每个 flag 常量代表一个独特的二进制位,所以它们可以通过按位或相加组合在一起,而不会产生冲突。例如:

  • Ltime 的值是 1 << 1,即 0b0010
  • Llongfile 的值是 1 << 3,即 0b1000

当我们使用 log.SetFlags(Ltime | Llongfile) 时,相当于将 0b0010 | 0b1000 组合成 0b1010,即同时启用了时间和文件名短格式显示。

通过这种位运算方式,可以组合各种 flag 选项,而不必为每种组合重新定义一个新的常量。

3. 使用按位或组合 flag 的优势

  • 灵活性高:可以自由选择多个选项的组合,满足不同需求,而不必逐一指定每个 flag
  • 可读性强:按位或组合表达式简单明了,清楚地显示启用了哪些功能。
  • 高效性:位运算本身效率高,计算量小,而且 flag 常量设计成二进制掩码,便于快速组合和解读。

4. 如何识别已设置的flag

当我们通过位或组合多个flag传递给log.SetFlags后,log包在输出日志时会检测该组合值,并根据不同的位设置来确定输出内容。

具体的识别方式:按位与(&)操作

假设我们设置了以下flag组合:

log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)

传入的flag组合会是一个整型值,log包会在生成日志时,通过按位与操作来判断每个flag是否存在。具体步骤如下:

  • 检查Ldate:使用按位与操作flags & Ldate,如果结果不为0,则表示Ldate已被设置,那么日志将包含日期信息。
  • 检查Ltime:同样,通过flags & Ltime,非零表示Ltime被设置,日志中将包含时间信息。
  • 检查Llongfile:按位检查flags & Llongfile,通过判断值来确定是否输出文件路径(完整路径)。

具体来看,假设我们使用log.Ldate | log.Ltime | log.Llongfile

  • Ldate的值为00000001
  • Ltime的值为00000010
  • Llongfile的值为00001000

将这些flag组合在一起后的整型值是00001011,它包含了所有的设置信息。

示例:代码实现flag识别的过程

log包的实现原理为例,可以大致模拟flag识别的过程。假设flags变量存储了当前的flag设置值,可以如下判断是否开启各个功能:

package main

import (
    "log"
)

func main() {
    flags := log.Ldate | log.Ltime | log.Llongfile

    if flags&log.Ldate != 0 {
        log.Print("日期已启用")
    }
    if flags&log.Ltime != 0 {
        log.Print("时间已启用")
    }
    if flags&log.Llongfile != 0 {
        log.Print("完整文件路径已启用")
    }
}

5. 使用展示

我们来看一个例子,假设这段代码位于 main.go 文件的第 10 行:

package main

import (
    "log"
)

func main() {
    log.SetFlags(log.Ltime | log.Lshortfile)
    log.Println("这是一个日志消息")
}

如果这段代码在 2024 年 11 月 3 日 15:04:05 执行,日志输出可能会是:

15:04:05 main.go:10: 这是一个日志消息

其中,15:04:05 是时间,main.go:10 是简化的文件名和行号。

6. 总结

使用按位或操作符 | 来配置日志 flag,可以让我们灵活地组合日志的不同显示选项,方便地自定义输出格式。这种方式不仅简化了代码,还提高了日志配置的灵活性和可读性。

到此这篇关于Go中log包异或组合配置妙用详解的文章就介绍到这了,更多相关Go log包异或组合内容请搜索恩蓝小号以前的文章或继续浏览下面的相关文章希望大家以后多多支持恩蓝小号!

原创文章,作者:IKLWD,如若转载,请注明出处:https://www.wangzhanshi.com/n/5643.html

(0)
IKLWD的头像IKLWD
上一篇 2024年12月17日 19:27:47
下一篇 2024年12月17日 19:27:49

相关推荐

  • go中结构体切片的实现示例

    在 Go 语言中,结构体切片是一种非常常用的数据结构,它结合了结构体和切片的特点,可以方便地存储和操作多个结构体实例。以下是关于 Go 结构体切片的详细介绍: 1. 结构体切片的定…

    Golang 2024年12月17日
  • go解析YAML文件(多文档解析)

    概述 摘要: 在kubernetes二次开发中,常用yaml文件来创建资源,比如Pod,deployment。在使用client-go创建资源之前,需要将yaml文件转换为资源对象…

    Golang 2024年12月17日
  • GO语言中ni,零值与空结构体的使用

    go语言的初学者,特别是java开发者新学习go语言,对于一些和java类似但是又有差异的概念很容易混淆,比如说go中的零值,nil 和 空结构体。本文就来详细探讨一下go中这些特…

    Golang 2024年12月17日
  • golang实现ip访问限制及提交次数

    在 Web 应用中,通常会需要对 IP 访问进行限制以及控制提交次数,以防止恶意攻击(例如暴力破解、DoS攻击、API滥用等)。为了实现这一功能,我们可以结合 Golang 的特性…

    Golang 2024年12月17日
  • Go语言内建函数len的使用

    在 Go 语言中,len 是一个非常常用的内建函数,它用于获取各种数据类型的长度或大小。掌握 len 的使用方法,可以帮助我们更高效地处理数据结构。本文将详细介绍 len 函数的使…

    Golang 2024年12月17日
  • golang打包成带图标的exe可执行文件

    golang(go语言)打包成带图标的 exe 可执行文件,步骤如下 1、生成 ico 图标 先准备好要作为图标的图片 然后将图片生成 ico 文件 笔者使用在线生成 ico 文件…

    2024年12月26日
  • go-zero创建RESTful API 服务的方法

    在 go-zero 中,创建 RESTful API 服务可以通过 goctl 命令快速完成。go-zero 提供了一种高效的方式来生成服务的项目结构、路由、请求和响应模型、以及处…

    Golang 2024年12月17日
  • golang常用库之pkg/errors包第三方错误处理包案例详解

    golang常用库之-pkg/errors包 背景 golang自带了错误信息包error 只提供了简单的用法, 如errors.New(),和errors.Error()用来传递…

    2024年12月29日
  • golang类型断言的实现示例

    在 Go 语言中,类型断言是一种机制,用于从接口类型获取其具体类型的值。这对于处理通过接口传递的值非常有用。以下是类型断言的基本概念、语法和示例。 1. 基本语法 类型断言的语法如…

    Golang 2024年12月17日
  • Go语言web框架Gin响应客户端的方式

    前言 Gin是一个用Go语言编写的web框架。它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍。如果你是性能和高效的追求…

    2024年12月17日

发表回复

登录后才能评论