Go高级知识
文章目录
代码编译过程
-
全局变量会进行全局初始化
1 2
type noticeRepository struct{} var Notice = ¬iceRepository{}
-
model 层为何不全局实例化?因为 model 层的结构体带有属性,如果全局初始化则 model 层结构体实例的属性可能会出现重复,导致数据异常!
示例:用户 A 获取了有数据的用户结构体,则会覆盖初始的 model 结构体,接着用户 B 查询不到任何数据时,则会拿到用户 A 的用户结构体数据,而不是空结构体。
扇出和扇入
通常情况下多个函数可以同时从一个channel接收数据,直到channel关闭,这种情况被称作扇出。这是一种将工作分布给一组工作者的方法,目的是并行使用CPU和I/O。
如果一个函数同时接收并处理多个channel输入并转化为一个输出channel,直到所有的输入channel都关闭后,关闭输出channel,这种情况就被称作扇入。
死锁、活锁和饥饿
死锁
死锁程序是所有并发进程 彼此等待 的程序。在这种情况下,如果没有外界的干预,这个程序将永远无陆恢复。
活锁
活锁是正在 主动执行 并发操作的程序,但是这些操作无战向前推进程序的状态。
你曾经在走廊走向另一个人吗?她移动到一边让你通过,但你也做了同样的事情。所以你转到另一边,但她也是这样做的。想象一下这个情形永远持续下去,你就明白了活锁。
饥饿
饥饿是在任何情况下,并发进程都无法获得执行工作所需的所有资源。
饥饿通常意味着有一个或多个贪婪的并发进程,它们不公平地阻止一个或多个井发进程,以尽可能有效地完成工作,或者阻止全部并发进程。
引入私有仓库报错的解决方案
-
配置 git 全局变量
1 2
git config --global url.ssh://git@gitlab.xxx.com/.insteadof https://gitlab.xxx.com/ git config --global url.https://gitlab.xxx.com/.insteadof http://gitlab.xxx.com/
-
全局生效:go env -w GOPRIVATE=gitlab.xxx.com [或当前终端生效:export GOPRIVATE=gitlab.xxx.com]
-
go get gitlab.xxx.com/xxxx@v0.0.1
-
go mod tidy && go mod vendor
go.mod 引入本地包
|
|
跳出多重循环的高级 break 用法说明
在循环外使用 label 标记定义退出哪一层循环。
|
|
golang ast初探:一个懒人源码分析工具
throw
其实 go 语言源码中一些地方有一些 throw 调用,这个函数会打印相应的 fatal msg,并退出整个程序,因为这类报错被 go 语言认为无法动态修复的崩溃。所以这类奔溃与 panic 不同,属于无法通过 defer 和 recover 捕获的崩溃(因为无法修复)。
map:熟悉 go 语言的开发者都知道,在 go 多协程架构使用便利的情况下,往往存在很多线程不安全的变量,map 就是其中最经典的栗子,当在并发下,在没有添加读写锁的情况下对 map 进行写、读写操作时,也会抛出 throw 崩溃。
需要注意的是,这类崩溃是直接 down 掉整个进程的,所以我们线上使用 go 语言进行应用开发时,一定要记得使用 supervisor 之类的进程管理工具,确保进行崩溃后先拉起来,再进行修复。否则会产生大面积机器完全宕机的情况。
再需要注意的一点是,go 语言中一个进程往往有很多 goroutinue 在同时进行,如果发生 throw 奔溃时,整个进程都会被关掉,如果通过日志,会发现打印了无数堆栈信息的日志(所有 goroutinue 的日志),这时候千万不要在堆栈日志上下功夫了,因为打印出来的都是正常日志,只需要查看日志中的 fatal 关键字即可找出真正的问题所在。
|
|
uinptr && unsafe.Pointer
两者都是数据类型。
uintptr用来进行指针计算,因为它是整型,所以很容易计算出下一个指针所指向的位置。
unsafe.Pointer是特别定义的一种指针类型,它可以包含任意类型变量的地址。
静态代码分析工具
pre-commit hook
在项目开发中,我们都会使用到 git,因此我们可以将代码静态检查放在一个 git 触发点上,而不用每次写完代码手动去执行 golangci-lint run 等命令。这里,我们就需要用到 git hooks。
git hooks 是 git 的一种钩子机制,可以让用户在 git 操作的各个阶段执行自定义的逻辑。git hooks 在项目根目录的 .git/hooks 下面配置,配置文件的名称是固定的,实质上就是一个个 shell 脚本。根据 git 执行体,钩子被分为客户端钩子和服务端钩子两类。
客户端钩子包括:pre-commit、prepare-commit-msg、commit-msg、post-commit 等,主要用于控制客户端 git 的提交工作流。服务端钩子:pre-receive、post-receive、update,主要在服务端接收提交对象时、推送到服务器之前调用。
使用go自带的vet工具,是比较简单的工具,无法递归检查整个服务的代码
|
|
使用 golangci-lint
|
|