首页 > 其他分享 >Go语言精进之路读书笔记第20条——在init函数中检查包级变量的初始状态

Go语言精进之路读书笔记第20条——在init函数中检查包级变量的初始状态

时间:2024-02-13 10:55:06浏览次数:36  
标签:20 函数 读书笔记 包级 init func sql Go

20.1 认识init函数

init函数的特点:

  • 运行时调用,Go程序中不能显式调用
  • 顺序执行,等待一个init函数执行完毕并返回后再执行下一个init函数
  • 在整个Go程序生命周期内仅会被执行一次
  • 先被传递给Go编译器的源文件中的init函数先被执行,同一个源文件中的多个init函数按声明顺序依次执行。但不要依赖init函数的执行次序

20.2 程序初始化顺序

init函数的执行顺位排在其所在包的包级变量之后

20.3 使用init函数检查包级变量的初始状态

1.重置包级变量值

// $GOROOT/src/flag/flag.go
// commandLineUsage使用了flag包的另一个导出包变量Usage
// 用户将自定义usage赋值给Usage后,就相当于改变了CommandLine变量的Usage
func init() {
    CommandLint.Usage = commandLineUsage
}

// $GOROOT/src/context/context.go

// closedchan是一个可重用的处于关闭状态的channel
var closedChan = make(chan struct{})
func init() {
    close(closedChan)
}

2.包级变量进行初始化,保证其后续可用

// $GOROOT/src/regexp/regexp.go
// Bitmap used by func special to check whether a character needs to be escaped.
var specialBytes [16]byte

// special reports whether byte b needs to be escaped by QuoteMeta.
func special(b byte) bool {
    return b < utf8.RuneSelf && specialBytes[b%16]&(1<<(b/16)) != 0
}
// 负责完成对内部特殊字节数组的初始化,这个特殊字节数组被包内的special函数使用,用于判断某个字符是否需要转义
func init() {
    for _, b := range []byte(`\.+*?()|[]{}^$`) {
        specialBytes[b%16] |= 1 << (b / 16)
    }
}

// $GOROOT/src/net/addrselect.go
// 对rfc6724policyTable这个未导出包级变量进行反转排序
func init() {
    sort.Sort(sort.Reverse(byMaskLength(rfc6724policyTable)))
}

// $GOROOT/src/net/http/h2_bundle.go
// 根据环境变量DEBUG的值对一些包级开关变量进行赋值
var (
    http2VerboseLogs    bool
    http2logFrameWrites bool
    http2logFrameReads  bool
    http2inTests        bool
)

func init() {
    e := os.Getenv("GODEBUG")
    if strings.Contains(e, "http2debug=1") {
        http2VerboseLogs = true
    }
    if strings.Contains(e, "http2debug=2") {
        http2VerboseLogs = true
        http2logFrameWrites = true
        http2logFrameReads = true
    }
}

3.init函数中的注册模式

lib/pq包访问PostgreSQL数据库。

import (
    "database/sql"
    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full")
    if err != nil {
        log.Fatal(err)
    }

    age := 21
    row, err := db.Query("SELECT name FROM users WHERE age = $1", age)
    ...
}

// github.com/lib/pq/conn.go
...
func init() {
    sql.Register("postgres", &Driver{})
}

空别名方式导入lib/pq的副作用就是Go运行时会将lib/pq作为main包的依赖包并会初始化pg包,于是pg包的init函数得以执行。

pg包将自己实现的SQL驱动(driver)注册到sql包中,当应用层代码在打开数据库的时候传入驱动的名字(这里是postgres),通过sql.Open函数返回的数据库实例句柄对应的就是pg这个驱动的相应实现。

这种注册模式实质是一种工厂设计模式的实现,sql.Open函数就是该模式中的工厂方法,它根据外部传入的驱动名称生产出不同类别的数据库实例句柄。

标准库image包获取各种格式的图片的宽和高。

4.init函数中检查失败的处理方法

init函数在检查包数据初始化状态时遇到失败或者错误的情况,建议直接调用panic或者log.Fatal等函数记录异常日志,让程序快速退出。

标签:20,函数,读书笔记,包级,init,func,sql,Go
From: https://www.cnblogs.com/brynchen/p/18014390

相关文章

  • 2024/2/12学习进度笔记
    sparkrdd持久化frompysparkimportSparkContext,SparkConfimportosimportrefrompyspark.storagelevelimportStorageLevelos.environ['SPARK_HOME']='/export/server/spark'PYSPARK_PYTHON="/root/anaconda3/envs/pyspark_env/bin......
  • WC 2024 游记
    WC2024游记Day-2~Day-1在酒店颓废。Day0不存在的一天。Day1报到日。上午从酒店搬了出来(行李箱好重qvq)。坐上了cq神奇的地铁(轻轨),看着地铁上天下地的感觉还是很奇妙的。大抵是中午的时候到了育才。离育才最近的地铁口可以坐环线(转圈圈!),cq地铁真神奇。到了门口发现每......
  • P4559 [JSOI2018] 列队 题解
    题目链接:列队半年前mark的题,结果现在一下子就会做了。顺便写写我的手玩过程和复杂度说明。考虑比较特殊的情况:比较特殊的,发现从黑色到红色区间我们无论咋选择,由于\(\left|a_{right}-a_{left}\right|\),这玩意如果\(right\)表示红色的一边,那么这个绝对值可以直接拆掉,那么......
  • 2024牛客寒假算法基础集训营1
    2024牛客寒假算法基础集训营1A解题思路:按照\(dfs\)出现顺序暴力判断即可。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusingi128=__int128_t;usingpiii=pair<ll,pai......
  • GDKOI2023 错排
    逆天。转化后的题意\(q\)组询问,求有\(n-m\)个自由元素,\(m\)个限制元素的错排问题。\(1\len,m,q\le2\times10^5\)首先写出两种组合意义的转移方程:\[\begin{aligned}f(n,m)&=f(n,m-1)-f(n-1,m-1)\\f(n,m)&=(m-1)f(n-1,m-2)+(n-m)f(n-1,m-1)\end{aligned}\]......
  • [WUSTCTF2020]朴实无华
    [WUSTCTF2020]朴实无华robots.txt里发现提示打开这个页面,虽然页面里没有有用的信息,但是在响应头里发现了另一个页面提示打开发现代码<?phpheader('Content-type:text/html;charset=utf-8');error_reporting(0);highlight_file(__file__);//level1if(isset($_GET......
  • [MRCTF2020]Hello_ misc
    [MRCTF2020]Hello_misc压缩包里有1个压缩包和png图片压缩包有密码,先对图片进行解析发现红色通道里还藏有一张图片得到zip压缩包密码:!@#$%67*()-+这个密码是图片中藏着的压缩包的密码,输入后打开里面有一个out.txt文件12725563191127191631271272556319163......
  • 2024牛客寒假算法基础集训营2个人补题题解(K、D)
    比赛链接:2024牛客寒假算法基础集训营2K、TokitsukazeandPassword(easy)题面看着很难实际上只要暴力的东西,赛时看了眼题面就溜了血亏爆搜,枚举\(abcd\)和_可能的值,枚举的情况只有\(9*8*7*6*9=27216\)种。判断按照枚举出的对应值排列出的密码是否满足条件,满足就\(ans++\)写完......
  • P8674 [蓝桥杯 2018 国 B] 调手表
    原题链接题解一道思维题由于闹钟是圆的,所以从任意一个分钟数调到另外任意一个分钟数最多要按多少次相当于从点0调到1~n-1任意一点最多要按多少次可以把1~n看成一个一个点,就相当于单源最短路了md,好巧妙code#include<bits/stdc++.h>usingnamespacestd;structrefresh{......
  • 24/02/12 [六省联考 2017] 组合数问题
    题目描述组合数\(C_n^m\)表示的是从\(n\)个互不相同的物品中选出\(m\)个物品的方案数。举个例子,从\((1,2,3)\)三个物品中选择两个物品可以有\((1,2)\),\((1,3)\),\((2,3)\)这三种选择方法。根据组合数的定义,我们可以给出计算组合数\(C_n^m\)的一般公式:\[C_n^m......