Go 1.9.2 的 bug

最近写了一段代码,精简一下大概是这样: type config struct { fk2Opts map[string]string } type doublebuffer struct { c1 config c2 config currentIdx int64 l sync.RWMutex } var option doublebuffer func readConfig(key string) bool { option.l.RLock() defer

松一口气

这周末终于把 《Go 高级编程》里我负责的章节写完了,松一口气。之前写的时候还是挺苦逼的,8 个月将近 20 篇内容,工作日休息日都在想要怎么系统化地去总结相关的知识。收获还是不少的。但是太苦了。一直在多线程思考 orz 顺利的话应该按部就班地半年内出版,最感谢的还是柴大这条大粗腿了,柴大好棒,能让我只靠 1/3 的内容就能让名字留在铅字资料上~ 当然了,因为自身以前这方面总结的资料不多,所以写出来的东西肯定还是或多或少有一些问题的,今年剩下的四个月,会继续对已经写完的东西做完善和补充,但肯定没有之前压力大了。 对于个人来说,通过这本书,把所有 web 领域相关的知识全部进行了梳理和总结(

Go 系列文章 9: slice

slice 和 array 要说 slice,那实在是太让人熟悉了,从功能上讲 slice 支持追加,按索引引用,按索引范围生成新的 slice,自动扩容等,和 C++ 或 Java 中的 Vector 有些类似,但也有一些区别。 不过 Go 里的 slice 还有一个底层数组的概念,这一点和其它语言不同。 runtime/slice.go type slice struct

Go 系列文章 8: select

原文地址: https://github.com/cch123/golang-notes 汗,写完这篇就发现 Go 目前的 master 分支上 select 的实现有所修改,比如文中的 hselect 结构体已经消失了。之后还是抽时间分析分析新版。。 select 本身是 Go 提供的一个语法糖,每次你写 select { } 的时候,实际上是相当于调用了一大堆函数。。只是 Go 的 runtime 内部帮你把这些复杂性屏蔽掉了。但是屏蔽也是有代价的,因为现在为止(

Go 系列文章 7: map

这次的 ascii 图太多了。。。粘到 blog 里毁灭性的不能看,所以还是看原文吧 orz https://github.com/cch123/golang-notes/blob/master/map.md

packt 出版的书吐槽

从办了双币信用卡开始买英文原版书以后,陆陆续续已经买了几十本了(看得完吗你。 嗯,其实大多数国外出版社的书质量还是可以的,比如 O'Reilly,NoStarch,Manning,Apress,微软之类的出版社。特别是 NoStarch,虽然每本书上面可能都有一条不明所以的彩边,而且封面以屎黄色(汗为主,不过感觉他们的封面设计的都挺好看的,比如下面这样的: 应该是有专门的封面设计师来做的吧。 manning 出版社的一般都是一些少数民族人物的绘作: 挺好看的。 O'Reilly 嘛,大家都熟悉,就是各种各样的动物书: Apress 相对就死板一些: 微软也差不多,沉闷的大公司风格: 唯独这个 Packt。。不知道该怎么吐槽了,

Go 系列文章6: syscall

系统调用 原文地址: https://github.com/cch123/golang-notes/blob/master/syscall.md 概念 一图胜千言: + - - - - - - - - - - - - - - - User Mode - - -

Go 系列文章5 : 定时器

去年和董大大聊过两句 Go 的定时器,当时大概看了眼代码是四叉堆,不过实现细节忽略掉了。 前几天和刘丁还有董大又聊起定时器的事情,正好就借这个机会把 Go 的定时器实现完整梳理一遍。不涉及 netpoll,因为我还没有看完这部分代码。 董大的文章网络和定时器怎么结合都提到了,感兴趣的可以看 这里。 看到两边有一样的图不要奇怪,所以这篇文章可以算联动吗,哈哈。 定时器算是服务端程序是非常重要的功能,特别是和网络或者文件系统打交道的系统,我们都会对每一次 IO 操作都加上合理的超时,以避免各种特定情况下的资源泄露。所以了解定时器的实现还是挺重要的。 PS: 看来 ghost 对 unicode 字符串组成的图支持也不是特别好,如果你觉得别扭,可以查看这篇文章的原文,

concurrency in go 读书笔记

《concurrency in go》这本书出版于 2017 年八月,里面有些观点还是蛮新颖的,烂大街的我就先不写了,重点写写书里提到的,我之前忽视的观点,以及一些奇技淫巧。 锁的粒度太大的话,有可能造成其它的 goroutine 饥饿 package main import ( "fmt" "sync" "time" ) func main() { var wg sync.WaitGroup

Go 系列文章4 : 调度器

推荐用 stackedit 导出后看,文章中有不少 mermaid 图表,ghost 博客不支持展示。原始的 markdown 保存在:这里 写得稍微有点乱,主要是按自己看代码的顺序来记录的,也不是出书,就这样吧。 PS: 新人不推荐刚学 Golang 就去看调度器代码,这部分代码个人觉得写得很乱。 调度 基本数据结构 goroutine 在 runtime 中的数据结构: // stack 描述的是 Go 的执行栈,下界和上界分别为 [lo,

2018 年的几个目标

18 年已经到 6 月份了,定目标可能有点太晚了,不过有总比没有强,作为一个硕士毕业已经工作四年的程序员,切实地感觉到了时间的重要性,需要按照规划来用,不能像年轻人那样挥霍了。 完成 Golang 的大部分源代码阅读,并完成 golang-notes 完成 redis 3.0 的源代码阅读并有总结产出 完成 nginx 的源代码阅读并有总结产出,这个坑遗留得有点久,14 年刚毕业的时候就挖了,汗 完成 nats 源码阅读并有总结产出 完成 Go 高级编程中

livelock

最近在看的 《concurrency in go》 里有这么一个例子: package main import ( "fmt" "sync" "sync/atomic" "time" ) func main() { cadence := sync.NewCond(&sync.Mutex{}) go func() { for range

blog 升级了。。

最近在写 golang-notes 的时候,看到 hexo 的 blog 支持直接展示 plantuml 和 mermaid 图表,折腾了一晚上发现并不是很好用。。。这些功能都是以插件形式支持,但在每个 blog 主题下又都需要自己配置,主题显然也没有什么统一的规范,自己用的话还是会碰到蛋疼的问题。此外 hexo 也不支持直接把图片上传到自己的 blog (别跟我说传什么七牛 cdn 之类的,几年后要是人挂了,你这就蛋疼了)。 虽然 ghost 已经商业化,且官网直接把 download

事故驱动开发

软件工程发展了这么多年,直到现如今,业界还是比较喜欢讨论 TDD,BDD,DDD。 虽然最后那个和前两个不太像是同一个维度的东西,不过因为都是 xDD,我们就先放在一起了嗯。每一种理论都有不少拥趸和践行者,都希望在各自的不归路上一路走到黑。至于每一种理论是否能为大众所接受,那就不好说了。犹记得某届 gopherchina,七牛的 CEO 去讲 http 测试,然后被人喷讲的太渣,没有深度,可能这位同学的潜台词是:我们想要的是画满了框图的架构 ppt,就是想看各种方块啊线条啊什么的,你却给我们来讲怎么写 test 和这些看起来 low 的不行的 test。

goroutine 的状态切换

在 runtime2.go(go 1.10) 中定义了 goroutine 生命周期中所有可能的状态,虽然状态不多,不过其状态切换的可能性还是蛮多的,整理了一张图: 带上 GC 以后,图会比较乱,去掉 GC 相关的状态切换以后,会清爽许多。这里所有的 goroutine 状态切换都是由 runtime 的函数触发的,我们把 runtime 字样也从图上删除: 抽时间写写状态切换的文章。 再来一张 p 状态切换的:

分布式系统中的不可靠复制问题

在《Designing Data-Intensive Application》一书中为当今大多数的互联网系统下了个定义,即数据密集型系统。在数据密集型系统中我们要应对的是数据的爆炸性增长问题。 为了应对问题我们采用了一些手段,比如 partition、replication,但这些手段,在一些场景或语言受限的情况下会带来一些麻烦的问题。本文主要讲一讲复制方面的问题。 说到复制 replication,可能大多数人第一印象都是存储系统中的复制,比如 MySQL 中基于 binlog 的复制,redis 中基于操作日志的复制,zk/etcd/kafka 中基于特定算法的复制(实质上也是基于 log 的复制),等等。但复制的概念本身实际上是很广的,

Go 系列文章3 :plan9 汇编入门

plan9 assembly 完全解析 众所周知,Go 使用了 Unix 老古董(误 们发明的 plan9 汇编。就算你对 x86 汇编有所了解,在 plan9 里还是有些许区别。说不定你在看代码的时候,偶然发现代码里的 SP 看起来是 SP,但它实际上不是 SP 的时候就抓狂了哈哈哈。 本文将对 plan9 汇编进行全面的介绍,同时解答你在接触 plan9 汇编时可能遇到的大部分问题。 本文所使用的平台是

[译]Go 和 interface 探究

这篇和之前的汇编那篇一样,都是翻译自 github 的 go-internals 这个项目,我的翻译地址是: https://github.com/cch123/go-internals 这篇写的比较长,如果讲深度的话。。那自己真是惭愧到不好意思去写 interface 的文章了。 不过还是要写,因为看这种基于汇编分析问题的东西,对于大多数人来说还是比较难。这篇其实也不能算面面俱到,而且作者的研究方法是从 binary asm 反推实现原理,实际上还可以直接去看编译器的代码的。 废话不多说,如下。 $ go version go version go1.

Go 系列文章2:Go 程序的启动流程

Bootstrap locate entry point 思路,找到二进制文件的 entry point,在 debugger 中确定代码位置。 使用 gdb: (gdb) info files Symbols from "/home/ubuntu/exec_file". Local exec file: `/home/ubuntu/exec_file', file type

Go 系列文章1:Channel 从使用到源码分析

说明,做 Go 开发也有不短的时间了,积累了不少工具,感觉是时候开这么个坑了。源码阅读这种事情,别人发文、出书是别人的事情,如果没有自己尝试做一遍始终还是会少得到很多东西。最近感觉时机成熟,因为自己没有之前那么菜了,所以开这个坑。慢慢填上。内容是读 1.10 的源代码。用 stackedit 写完以后同步到 github 上,这里是原始仓库:golang-notes。 更新主要还是在 github 吧,主要是一些流程图性质的东西,这个挫逼博客不能支持啊,汗。 Channel go

协作/非协作式抢占

Go 最近有一个比较有意思的 proposal,提出要将协作式的抢占调度修改为非协作式的抢占调度,并使 Go 的每一条指令理论上都可以被抢占。起因是因为之前有类似这样的问题。当然,社区里遇到问题的人很多,如果你感兴趣,还可以看看这些 github 上的 issue:#543, #12553, #13546, #14561, #15442, #17174, #20793, #21053。 之前的协作式抢占是怎么一回事呢,我翻译的这篇 里其实已经有提及,该文中提到的函数中的 prologue 和 epilogue 即是可以执行调度的一个典型时机(但不是全部,此外还包括有

[译]go 和 plan9 汇编

本文翻译自: https://github.com/teh-cmc/go-internals 的第一章。之后如果有余裕,这个项目会一直跟进翻译。 . --> Chapter I: Go 汇编入门 在深入学习 runtime 和标准库的实现之前,我们需要先对 Go 的汇编有一定的熟练度。这份快速指南希望能够加速你的学习进程。 本章假设你已经对某一种汇编器的基础知识有所了解 涉及到架构相关的情况时,请假设我们是运行在 linux/amd64 平台上 学习过程中编译器优化会打开。 Table of Contents "Pseudo-assembly&

如何在 kv 系统中支持简单的 SQL

现在部门内进行数据收敛,特征相关的指标会逐渐收敛到 XFS 系统中。目前已经建设有 OFS(order feature system)、PFS(passenger feature system)。年后会建设 DFS(driver feature system)。 这些系统有共同的特征,根据 XID + 几个额外的参数来进行特征查询。而特征的具体存储可能是在 Rockstable(未来也可能是在 fusion),或者是在 MySQL,还可以来源于其它跨部门第三方系统的 API。 之前 XFS 对外主要提供

使用 debugger 学习 golang

常见的工程语言可分为解释型和编译型两种,比如写 php 的,一般就不怎么在乎 debugger 之类的东西。为什么?~~如果真出了问题,我可以临时把出问题的服务机器从线上服务中摘除出来,甚至申请一个较高的权限去修改代码,然后到处去 die/echo。虽然有人说这么做不太好,或者一般公司也不给开权限。不过着急的时候,这个肯定是可行的。~~然而像 java/go 这种编译型的就比较麻烦了。线上一般只有程序的运行环境而没有编译环境。就算是在线下,每次去加一行 fmt.Println 或者 System.out.println 都去编译一遍代码也是会明显降低幸福感的事情(当然这里有人说现在

你的负载均衡真的均衡么?

公司内部有一个流传很广的负载均衡算法,大概的流程如下: 数组元素对应的是 ip+port 列表,形如下面这样: 100.69.62.1:3232 100.69.62.32:3232 100.69.62.42:3232 100.69.62.81:3232 100.69.62.11:3232 100.

开源书

最近在和 chai 大一起写开源书 advanced go programming book。实际上这个项目 16 年就开始了(汗。。最开始放在闭源仓库里,热情高涨的时候写两句。不过 private 的东西,总感觉像 dev/null 一样,和在只有自己能看到的小本本上写日记差不多,写久了以后会感觉有点没劲。 写书是一个很好的过程,系统化地总结学习过的知识,锻炼毅力和语言表达能力。不管哪种职业,语言表达能力和梳理能力都是必备的。顺便还能达到某些不可告人的目的(233。 具体可以参见这里: https://github.com/

clean architecture(下)

接上篇 模块 最早的时候,程序员们为了重用代码,会直接把代码 #include 到自己的项目中来,然后把库代码和应用代码一起编译出一个可执行应用。这个时间点,library 是通过源代码分发的。但是那个时候外部存储设备非常慢,而内存则非常贵并且容量很有限。没有办法把所有代码都放在内存中进行编译,这样编译器就需要多次从外部存储设备中读取源代码,然后多次访问巨慢的外部存储。可以预见,库的代码越多,可能会导致程序的编译过程就越慢,为了缩短编译时间,程序员们想出了可以把库和 application 分开编译的法子: 只要把 library 加载到固定的内存位置,例如 2000,那么我们就可以直接使用编译好的 library 了。 不过这种做法很快遇到了问题,程序自己要使用的内存很快就超过了

clean architecture(上)

这半年来和同事陆陆续续有一些关于业务的代码、框架方面的争论,期间阅读过一篇陶师傅给的,推销 DCI 模式的文章/论文,认真地做了笔记。年底了,又有美团的人跳出来说互联网的业务也越来越复杂了,传统的糙快猛已经满足不了当下的需求,我们必须要认真考虑设计,而不是在学到了样子没学到根本的敏捷开发思想之上堆屎。看起来现在有不少人把矛头指向了曾经奉为圭臬的 OO 和 web 开发中最常见的 MVCL(S) 分层以及国人学了半瓶水的敏捷开发,并且各自提出了一些所谓的解决方案,比如 DCI 号称解决了 OO 驱动的开发模式下代码难以和需求所对应,而 DDD 也解决了项目上了规模以后,代码和业务描述脱节难以理解的问题。(这么看来两者解决的都是一样的问题。 虽然通过阅读,

recover 并不是无懈可击的

曾经天真地认为只要严格遵守有 go 必有 recover 就能保证程序永不宕机。直到有人对开源库有了类似下面这样的误用: package main func main() { var a = map[int]int{} defer func() { if err := recover(); err != nil { println("oh no") } }() go func() { defer func() { if err

ApsaraCache 源码 diff 分析

阿里最近开源了新项目,叫 ApsaraCache,号称对 redis 做了一些优化,但开源分步骤(明显是你们没开发完吧)逐渐放出。这也进一步体现了大公司技术栈的混乱,相信在阿里内部这种类 redis 的玩艺儿绝对也不少。不过不扯这个。在 ApsaraCache 开源一期的优化中,主要有两个功能点: 在 redis 4.0 的基础上增加了 memcached 协议的支持 对短连接的情况进行了优化 把 ApsaraCache 的代码 down 下来用 Beyond Compare
京ICP备15065353号-1