4.1 Go语言中包(Packages)基础知识

Python013

4.1 Go语言中包(Packages)基础知识,第1张

先看一下目录结构,注意这里的src名称是必须的,go在设置了GOPATH后,默认会添加src去寻找package,暂未查询是否有方法不按照src查询

根据上面的描述,Go语言中通过包中函数的名称来区分公共函数和私有函数,我们在main函数中是无法调用myPrivateFunc的

此时如果执行通过go run方式执行,会看到如下的提示信息,这与大部分语言对于包管理方式相关,所以我们通过两种不同的方法来让代码执行起来

返回如下,这里面对我们后续执行有影响的两个参数GO111MODULE和GOPATH

如果要使用gopath模式引用包,则需要关闭mod模式

设置GOPATH为当前路径,即main.go所在的路径

此时再查看go env时,GOPATH已经发生改变

我们再次尝试执行代码

可以看到public函数被调用

学完了 net/http 和 fasthttp 两个HTTP协议接口的客户端实现,接下来就要开始Server的开发,不学不知道一学吓一跳,居然这两个库还支持Server的开发,太方便了。

相比于Java的HTTPServer开发基本上都是使用Spring或者Springboot框架,总是要配置各种配置类,各种 handle 对象。Golang的Server开发显得非常简单,就是因为特别简单,或者说没有形成特别统一的规范或者框架,我发现了很多实现方式,HTTP协议基于还是 net/http 和 fasthttp ,但是 handle 语法就多种多样了。

先复习一下: Golang语言HTTP客户端实践 、 Golang fasthttp实践 。

在Golang语言方面,实现某个功能的库可能会比较多,有机会还是要多跟同行交流,指不定就发现了更好用的库。下面我分享我学到的六种Server开发的实现Demo。

基于 net/http 实现,这是一种比较基础的,对于接口和 handle 映射关系处理并不优雅,不推荐使用。

第二种也是基于 net/http ,这种编写语法可以很好地解决第一种的问题,handle和path有了类似配置的语法,可读性提高了很多。

第三个基于 net/http 和 github.com/labstack/echo ,后者主要提供了 Echo 对象用来处理各类配置包括接口和handle映射,功能很丰富,可读性最佳。

第四种依然基于 net/http 实现,引入了 github.com/gin-gonic/gin 的路由,看起来接口和 handle 映射关系比较明晰了。

第五种基于 fasthttp 开发,使用都是 fasthttp 提供的API,可读性尚可,handle配置倒是更像Java了。

第六种依然基于 fasthttp ,用到了 github.com/buaazp/fasthttprouter ,有点奇怪两个居然不在一个GitHub仓库里。使用语法跟第三种方式有点类似,比较有条理,有利于阅读。

基本设计思路

类型转换、类型断言、动态派发。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 映射存储组),每个组只进行一次访问,组内每个协程会获得对应结果的一个拷贝。

结构:

逻辑:

细节:

部件:

如有错误,请批评指正。