类型转换、类型断言、动态派发。iface,eface。
反射对象具有的方法:
编译优化:
内部实现:
实现 Context 接口有以下几个类型(空实现就忽略了):
互斥锁的控制逻辑:
设计思路:
(以上为写被读阻塞,下面是读被写阻塞)
总结,读写锁的设计还是非常巧妙的:
设计思路:
WaitGroup 有三个暴露的函数:
部件:
设计思路:
结构:
Once 只暴露了一个方法:
实现:
三个关键点:
细节:
让多协程任务的开始执行时间可控(按顺序或归一)。(Context 是控制结束时间)
设计思路: 通过一个锁和内置的 notifyList 队列实现,Wait() 会生成票据,并将等待协程信息加入链表中,等待控制协程中发送信号通知一个(Signal())或所有(Boardcast())等待者(内部实现是通过票据通知的)来控制协程解除阻塞。
暴露四个函数:
实现细节:
部件:
包: golang.org/x/sync/errgroup
作用:开启 func() error 函数签名的协程,在同 Group 下协程并发执行过程并收集首次 err 错误。通过 Context 的传入,还可以控制在首次 err 出现时就终止组内各协程。
设计思路:
结构:
暴露的方法:
实现细节:
注意问题:
包: "golang.org/x/sync/semaphore"
作用:排队借资源(如钱,有借有还)的一种场景。此包相当于对底层信号量的一种暴露。
设计思路:有一定数量的资源 Weight,每一个 waiter 携带一个 channel 和要借的数量 n。通过队列排队执行借贷。
结构:
暴露方法:
细节:
部件:
细节:
包: "golang.org/x/sync/singleflight"
作用:防击穿。瞬时的相同请求只调用一次,response 被所有相同请求共享。
设计思路:按请求的 key 分组(一个 *call 是一个组,用 map 映射存储组),每个组只进行一次访问,组内每个协程会获得对应结果的一个拷贝。
结构:
逻辑:
细节:
部件:
如有错误,请批评指正。
下面先写一段测试程序,然后看下运行结果:
运行结果:
发生了错误,提示:fatal error: concurrent map read and map write, map 发生了同时读和写了; 但是这个错误并不是每次运行都会出现,就是有的时候会出现,有的时候并不会出现,根据笔者多次运行结果(其他例子,读者可以自己尝试下)来看还会有另外一种报错就是:fatal error: concurrent map writes,就是map发生了同时写,但是只是读是不会有问题的。关于不同的运行结果小伙伴们可以自己写几个例子去测试下。下面就这两个错误的发生,笔者给出如下解释:
(1) fatal error: concurrent map read and map write
就是当一个goroutine在写数据,而同时另外一个goroutine要读数据就会报错,不过这个报错也很好理解:还没写完就读,读的数据会有问题,或者反过来还没读完就开始写了,同样会导致读取的数据有问题;
(2) fatal error: concurrent map writes
两个goroutine 同时写一个内存地址,这种操作也是不允许的,会导致一些比较奇怪的问题;
总体来看其实就是写map的操作和其他的读或者写同时发生了,导致的报错,做过几年开发的人可能会想到使用锁来解决,比如写map某个key的时候,通过锁来保证其他goroutine不能再对其写或者读了。
实现思路:
(1) 当写map的某个key时,通过锁来保证其他goroutine不能再对其写或者读了。
(2) 当读map的某个key时,通过锁来保证其他的goroutine不能再对其写,但是可以读。
于是我们马上想到golang 的读写锁貌似符合需求,下面来实现下:
再来看下运行结果:
发现没有报错了,并且多次运行的结果都不会报错,说明这个方法是有用的,不过在go1.9版本后就有sync.Map了,不过这个适用场景是读多写少的场景,如果写很多的话效率比较差,具体的原因在这里笔者就不介绍了,后面会写篇文章详细介绍下。
今天的文章就到这里了,如果有不对的地方欢迎小伙伴给我留言,看到会即时回复的。
1、服务器编程:以前你如果使用C或者C++做的那些事情,用Go来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。
2、分布式系统、数据库代理器、中间件:例如Etcd。
3、网络编程:这一块目前应用最广,包括Web应用、API应用、下载应用,而且Go内置的net/http包基本上把我们平常用到的网络功能都实现了。
4、开发云平台:目前国外很多云平台在采用Go开发,我们所熟知的七牛云、华为云等等都有使用Go进行开发并且开源的成型的产品。
5、区块链:目前有一种说法,技术从业人员把Go语言称作为区块链行业的开发语言。如果大家学习区块链技术的话,就会发现现在有很多很多的区块链的系统和应用都是采用Go进行开发的,比如ehtereum是目前知名度最大的公链,再比如fabric是目前最知名的联盟链,两者都有go语言的版本,且go-ehtereum还是以太坊官方推荐的版本。
自1.0版发布以来,go语言引起了众多开发者的关注,并得到了广泛的应用。go语言简单、高效、并发的特点吸引了许多传统的语言开发人员,其数量也在不断增加。
使用 Go 语言开发的开源项目非常多。早期的 Go 语言开源项目只是通过 Go 语言与传统项目进行C语言库绑定实现,例如 Qt、Sqlite 等。
后期的很多项目都使用 Go 语言进行重新原生实现,这个过程相对于其他语言要简单一些,这也促成了大量使用 Go 语言原生开发项目的出现。