大家好,我是煎鱼。 上个月面向读者的提问,我们针对 goroutine 泄露中都会看到的大头 runtime.gopark 函数进行了学习和了解,输出了 《Goroutine 一泄露就看到他,这是个什么?》。 有小伙伴提到,虽然我们知道了 runtime.gopark 函数的缘起和内在,但其实没有提到 runtime.gopark 的诱发因素,这是我们日常编码中需要关注的。 今天这篇文章就和大家一起围观 gopark 的 27 个诱发场景。为了方便阅读,我们会根据分类进行说明。 第一部分 标识 含义 waitReasonZero 无 waitReasonGCAssistMarking GC assist marking waitReasonIOWait IO wait waitReasonZero:无正式解释,从使用情况来看。主要在 sleep 和 lock 的 2 个场景中使用。 waitReasonGCAssistMarking:GC 辅助标记阶段会使得阻塞等待。 waitReasonIOWait:IO 阻塞等待时,例如:网络请求等。 第二部分 标识 含义 waitReasonChanReceiveNilChan chan receive (nil chan) waitReasonChanSendNilChan chan send (nil chan) waitReasonChanReceiveNilChan:对未初始化的 channel 进行读操作。 waitReasonChanSendNilChan:对未初始化的 channel 进行写操作。 第三部分 标识 含义 waitReasonDumpingHeap dumping heap waitReasonGarbageCollection garbage collection waitReasonGarbageCollectionScan garbage collection scan waitReasonDumpingHeap:对 Go Heap 堆 dump 时,这个的使用场景仅在 runtime.
大家好,我是煎鱼。 平时在日常工程中,我们常常会用到异常恐慌(panic)的记录和追踪。最常见的就是,线上 panic 了之后,我们总想从中找到一些蛛丝马迹。 我们很多人是看 panic 是看他的调用堆栈。然后就开始猜,看代码。猜测是不是哪里写的有问题,就想知道 panic 是由什么参数引起的? 因为知道了诱发的参数,排查问题就非常方便了。为此在 Go1.17,官方对这块的调用堆栈信息展示进行了优化,使其可读性更友好。 案例 结合我们平时所使用的 panic 案例。如下: func main() { example(make([]string, 1, 2), "煎鱼", 3) } //go:noinline func example(slice []string, str string, i int) error { panic("脑子进煎鱼了") } 运行结果:
大家好,我是煎鱼。 在 Go1.17 发布后,我们惊喜的发现 Go 语言他又又又优化了,编译器改进后产生了约 5% 的性能提升,也没有什么破坏性修改,保证了向前兼容。 他做了些什么呢,好像没怎么看到有人提起。为此今天煎鱼带大家来解读两新提案: 《Proposal: Register-based Go calling convention》 《Proposal: Create an undefined internal calling convention》 本文会基于提案讲解和拆解,毕竟分享新知识肯定要从官方资料作为事实基准出发。 背景 在以往的 Go 版本中,Go 的调用约定简单且几乎跨平台通用,其原因在于选用了基于 Plan9 ABI 的堆栈调用约定,也就是函数的参数和返回值都是通过堆栈上来进行传递。
大家好,我是煎鱼。 不得不说。我可是个经历过 Go 依赖管理群魔乱舞,Go modules 迁移一堆 BUG 的人儿,难顶… 为此当年我写了不少技术文章,希望给大家避坑。 如下: Go Modules 终极入门 干货满满的 Go Modules 知识分享 Go1.16 新特性:Go mod 的后悔药,仅需这一招 在近期 Go1.17 发布后,Go modules 带来了两大更新,煎鱼摩拳擦掌,他们分别是: 模块依赖图裁剪(module graph pruning) 延时模块加载(lazy module loading) 今天带大家一起来了解这两块内容,争取了解其为何物,背景又是什么。
大家好,我是煎鱼。 这两天看到官方博客的《Tidying up the Go web experience》,已经明确了优化 Go 站点的计划和安排了,为此今天和大家分享这一个好消息。 在之前 Go 官方推出了新的站点 go.dev,一个新的 Go 开发者中心: 以及提供给开发者查询 Go 包(package)和模块(module)信息的配套网站 pkg.go.dev: 看上去似乎美好,但其实原有的 golang.org 在继续提供 Go 发行版下载、文档和标准库的软件包的资料。 而其他 Go 网站,例如:blog.golang.org、play.golang.org、talks.golang.org 以及tour.golang.org,又都拥有额外的 Go 资料。这一切都有些零散和混乱。
大家好,我是煎鱼。 千呼万唤的,Go1.17 前几天终于发布了: 先前我写了几篇 Go1.17 新特性的文章,有兴趣的小伙伴可以看看: 一个新细节,Go 1.17 将允许切片转换为数组指针! 我要提高 Go 程序健壮性,Fuzzing 来了! 提了 3 年,Go1.17 终于增强构建约束! 今天的主题是泛型,众所皆知 Go1.18 泛型就会正式释出,都很期待,毕竟大更新,所有配套都会陆续有来! 其实,在 Go1.17 的此刻其实可以使用泛型了,泛型代码已合入 master 分支。 咱们只需要一点点操作,就能提前过上 Go 泛型的实验生活了。
大家好,我是煎鱼。 作为一个 Go 语言的使用大户,常常就有人冷不丁的,一下就泄露了…泄露了啥? 表象来看当然是 goroutine 泄露了,这时候就会有小伙伴开始跑去拉取 PProf。就会看到类似下面这张图: 重点会看到 runtime.gopark 这个函数,在所有的 goroutine 泄露中都会看到有,并且都会是大头。 既然是大头,也就会有许多朋友以为他是泄漏点,在那一顿猛查,那这个函数到底是什么,作用是? runtime.gopark 是何物 想要知道 runtime.gopark 函数是作用,最快的办法就是看源码了。其实现细节在 src/runtime/proc.go 文件中。 源代码如下: func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason waitReason, traceEv byte, traceskip int) { mp := acquirem() gp := mp.
大家好,我是煎鱼。 在 Go 语言中,有一个好像很好用,但却比较少人提及的功能,那就是 Go Plugin。目前在 Go 工程中普遍还没广泛的使用起来,覆盖率不高。 前段时间小咸鱼的同事问了他这玩具怎么用,他正想甩出一个链接,但发现…煎鱼竟然没写过,这不,Go 知识板块的文章地图得补全。 今天煎鱼就大家一起学习 Go Plugin! 是什么 Go Team 最早在 Go1.7 实验,在 Go1.8 正式引入了 Go Plugin 的机制。于 2016 年发布,一开始仅支持 Linux 实现: Go Plugin 机制实现了 Go 插件的加载和符号解析,能够支持将我们所编写的 Go 包编译为共享库(.
大家好,我是煎鱼。 最近看到了一个很有意思的话题,我们平时常常会用 Go 的内置函数 len 去获取各种 map、slice 的长度,那他是怎么实现的呢? 正当我想去看看 len 的具体实现时,一展身手,却发现竟然是个空方法: func len(v Type) int 看注解也没有 link 到其他 runtime 函数,那么 len 函数是如何被调用的呢? 先前看国外讨论 Go 计算 len 的文章时做了一些翻译和笔记(底下有参考链接),在此分享给大家,共同进步。 谜底 今天就由煎鱼带大家一同解开这个谜底。既然是谜底,那就一开始就揭开。 其实 Go 语言中并没有 len 函数的具体实现代码,他其实是 Go 编译器的 “魔法” ,不是实际的函数调用。
大家好,我是煎鱼。 现在是 2021 年 8 月份了,根据 Go 语言发布周期的 2,8 原则。Go 1.17 即将发布,在写这篇文章时,现在已经进行到了 rc2: 这意味着离 Go1.18 释出泛型的正式支持又近了一点点,社区中讨论泛型相关的周边功能的声音又多了起来。 今天要讨论的泛型版功能支持也是如此,分别包含:map(#47330)、slice(#45955)、container/set(#47331) 三种通用类型的支持。 我们主要展开 maps 和 slices,其余的都大同小异,理解核心思想就好。 maps 该提案建议定义一个新的包 maps,它将提供可用于任何类型的 map 的函数: 下面的描述侧重于描述 API 的提供: