大家好,我是煎鱼。 前几天在公众号分享了一篇 Go timer 源码解析的文章《难以驾驭的 Go timer,一文带你参透计时器的奥秘》。 在评论区有小伙伴提到了经典的 timer.After 泄露问题,希望我能聊聊,这是一个不能不知的一个大 “坑”。 今天这篇文章煎鱼就带大家来研讨一下这个问题。 timer.After 今天是男主角是Go 标准库 time 所提供的 After 方法。函数签名如下: func After(d Duration) <-chan Time 该方法可以在一定时间(根据所传入的 Duration)后主动返回 time.Time 类型的 channel 消息。
大家好,我是煎鱼。 最近金三银四,是面试的季节。在我的 Go 读者交流群里出现了许多小伙伴在讨论自己面试过程中所遇到的一些 Go 面试题。 今天的男主角,是 Go 工程师的必修技能,也是极容易踩坑的地方,就是 “Go 面试题:Go 结构体(struct)是否可以比较?” 如果可以比较,是为什么?如果不可以比较,又是为什么? 请在此处默念自己心目中的答案,再往和煎鱼一起研讨一波 Go 的技术哲学。 结构体是什么 在 Go 语言中有个基本类型,开发者们称之为结构体(struct)。是 Go 语言中非常常用的,基本定义: type struct_variable_type struct { member definition member definition .
大家好,我是煎鱼。 最近金三银四,是面试的季节。在我的 Go 读者交流群里出现了许多小伙伴在讨论自己面试过程中所遇到的一些 Go 面试题。 今天的主角,是 Go 面试的万能题 GMP 模型的延伸题(疑问),那就是 ”GMP 模型,为什么要有 P?“ 进一步推敲问题的背后,其实这个面试题本质是想问:”GMP 模型,为什么不是 G 和 M 直接绑定就完了,还要搞多一个 P 出来,那么麻烦,为的是什么,是要解决什么问题吗?“ 这篇文章煎鱼就带你一同探索,GM、GMP 模型的变迁是因为什么原因。 GM 模型 在 Go1.1 之前 Go 的调度模型其实就是 GM 模型,也就是没有 P。
大家好,我是煎鱼。 最近金三银四,是面试的季节。在我的 Go 读者交流群里出现了许多小伙伴在讨论自己面试过程中所遇到的一些 Go 面试题。 今天的主角,是大家在既有语言基础的情况下,学 Goroutine 时会容易纠结的一点。就是 “进程、线程都有 ID,为什么 Goroutine 没有 GoroutineID?”。 这是为什么呢,怎么做那些跨协程处理呢? GoroutineID 是什么 我们要知道,为什么大家会下意识的想去要 GoroutineID,下面引用 Go 语言圣经中的表述: 在大多数支持多线程的操作系统和程序语言中,当前的线程都有一个独特的身份(ID),并且这个身份信息可以以一个普通值的形式被很容易地获取到,典型的可以是一个 integer 或者指针值。这种情况下我们做一个抽象化的 thread-local storage(线程本地存储,多线程编程中不希望其它线程访问的内容)就很容易,只需要以线程的 ID 作为 key 的一个 map 就可以解决问题,每一个线程以其 ID 就能从中获取到值,且和其它线程互不冲突。
大家好,我是煎鱼。 前几天在读者交流群里看到一位小伙伴,针对 interface 的使用有了比较大的疑惑。 无独有偶,我也在网上看到有小伙伴在 Go 面试的时候被问到了: 今天特意分享出来让大家避开这个坑。 例子一 第一个例子,如下代码: func main() { var v interface{} v = (*int)(nil) fmt.Println(v == nil) } 你觉得输出结果是什么呢? 答案是: false 为什么不是 true。明明都已经强行置为 nil 了。是不是 Go 编译器有问题?
大家好,我是煎鱼。 前几天在读者交流群里看到一位小伙伴,在向大家咨询 Go 相关的技术问题。 疑问是:“各位大佬,我在学习 defer 遇到闭包的时候很懵逼,谁比较明白,能指点?” 疑问 他的疑问是下面这道 Go 语言的 defer 题目,大家一起看看: func main() { var whatever [6]struct{} for i := range whatever { defer func() { fmt.Println(i) }() } } 请自己先想一下输出的结果答案是什么。
大家好,我是煎鱼。 前几天在微信群看到几位大佬在讨论一个问题: ”字符串 len == 0 和 字符串 == "” ,有啥区别?“ 这是一个比较小的细节点,同时也勾起了我的好奇心,因此今天这篇文章就和大家一起研究一下他们两者有没有区别,谁的性能更好一些? 测试方法 在测试的方法中,我们分别声明了 Test1 和 Test2 方法: func Test1() bool { var v string if v == "" { return true } return false } func Test2() bool { var v string if len(v) == 0 { return true } return false } 在方法内部仅做了简单的变量类型声明,分别以 字符串 == "” 和 字符串 len == 0 为判断依据。
大家好,我是煎鱼。 前几天在读者交流群里看到一位小伙伴,发出了一个致命提问,那就是:“单机的 goroutine 数量控制在多少比较合适?”。 也许你和群内小伙伴第一反应一样,会答复 “控制多少,我觉得没有定论”。 紧接着延伸出了更进一步的疑惑:“goroutine 太多了会影响 gc 和调度吧,主要是怎么预算这个数是合理的呢?” 这是本文要进行探讨的主体,因此本文的结构会是先探索基础知识,再一步步揭开,深入理解这个问题。 Goroutine 是什么 Go 语言作为一个新生编程语言,其令人喜爱的特性之一就是 goroutine。Goroutine 是一个由 Go 运行时管理的轻量级线程,一般称其为 “协程”。 go f(x, y, z) 操作系统本身是无法明确感知到 Goroutine 的存在的,Goroutine 的操作和切换归属于 “用户态” 中。
大家好,我是慢一拍的后方记者煎鱼。 按照先前官方和文章的说法,Go 泛型预计是在 Go1.18 正式释出。 在 GopherCon 2020 Go Team AMA 时,要在今年底要能有生产环境的试用版上线,这是 rsc 所提出的一个管理目标。 转折点 近期出现了一个新的转折点,能够让大家在主干分支(master)上就能享受到泛型的功能。 而 master 分支对应了 Go1.17 的版本。因此未来将可以在 Go1.17 使用到泛型,这是一个比较惊喜的事情。 原因 这件事情为什么会突然发生呢?一切都得从背景说起。原本 Go 泛型是一直在 dev.typeparams 分支上进行研讨和开发。 由于泛型不是简单的一两个模块的代码变更,而是涉及大量的代码变更。
大家好,我是在打自己脸的后方记者煎鱼。 前几天我发表了文章《意见征集:Go1 要不要移除 GOPATH?》。 本次投票共有 592 人参与了投票。 结果如下: 绝大部分人支持移除 GOPATH,但建议保留的人依然占相当一部分。 最新进展 在近几天,在 go issues 上有人提出了新的提案:《proposal: cmd/go: maintain ‘classic’ vendor behaviour》。 该提案正式向 Go 官方提出了我们上一篇文章有提到的两点: Go 历史项目的维护问题。 Go1 兼容性保证的许诺。 摘选一部分核心观点给大家看看。