任何业务,都是从简单到复杂演进的。而在业务演进的过程中,技术是从单体向多模块、多服务演进的。技术的这一种演进方式。技术的这种演进方式的核心目的是复用代码、提高效率。我们来一起了解一下Go语言是如何通过模块化的管理,提升开发效率的。
Go语言中的包
什么是包?
在业务简单的时候,我们可以把代码写到一个Go文件中。但是随着业务的发展,如果代码都放在一个文件里,会变得难以维护,这时候就需要抽取代码,把相同业务的代码放在一个目录中。在Go语言中,这个目录叫做包。在Go语言中,一个包是通过package 关键字定义的,最常见的是main包,还有经常用到的fmt包,都是通过package 关键字声明的。 一个包就是一个独立空间,可以在包里定义函数、结构体等。这时,我们认为这些函数、结构体属于这个包。
package main
// package fmt
使用包
如果想要使用一个包里的函数或者结构体,就需要先导入这个包,才能使用,比如常用的fmt包。要导入一个包,需要使用 import 关键字;如果需要同时导入多个包,可以使用小括号,示例如下:
import (
"fmt"
"os"
)
// 使用小括号,每一行写一个要导入的包
作用域
包之前的导入和使用,就要提到作用域这个概念,因为只有满足作用域的函数才可以被调用。
在Java语言中,通过public、private这些修饰修饰一个类的作用域;
在Go语言中,并没有这样的修饰符,它是通过首字母大小写来区分,这也体现了Go语言的简洁。
Go语言作用域总结:
Go语言中,所有的定义,比如函数、变量、结构体等,如果首字母大写,那么就可以被其他包使用;
反之,如果首字母小写,就只能在同一个包内使用。
自定义包
我们也可以自定义包,通过包的方式把相同业务、相同职责的代码放在一起。在Go语言中,一个包对应一个文件夹,比如有一个util文件夹,里面有一个 string.go 文件,这个Go问阿金就属于util包,它的包定义就是:
|—— util
|—— string.go
package util
Go语言中的包是代码的一种组织形式,通过包把相同业务或者相同职责的代码放在一起。通过包对代码进行归类,便于维护以及被其他包使用,提高团队协作效率。
init函数
除了main函数外,Go语言还有一个特殊的函数 —— init,通过它可以实现包级别的一些初始化操作。init 函数没有返回值,也没有参数, 它优先于main 函数执行。
func init() {
// 代码
}
一个包中可以有多个init函数,但是它们的执行顺序不确定,所以如果定义了多个init函数,要确保它们是相互独立的,一定不要有顺序上的依赖。 那么init函数的作用是什么呢? 其实就是在导入一个包的时候,可以对包做一些必要的初始化操作,比如数据库连接和一些数据的检查,确保我们可以正确使用这个包。
Go 语言中的模块
如果包是比较低级的代码组织形式的话,那么模块就是更高级别的,在Go语言中,一个模块可以包含多个包,所以模块是相关包的集合。 在Go语言中,一个模块通常是一个项目,也可以是一个框架,比如常用的Web框架Gin。
go mod
Go语言提供了 go mod命令来创建一个模块(项目),通过命令可以创建一个文件夹,里面会有一个go.mod文件,示例如下:
go mod init gotest
go: creating new go.mod: module gotest
// go.mod
module gotest // 这一句是该项目的模块名,即gotest
go 1.14 // 这一句表示编译该模块至少需要 Go 1.14 版本的SDK
提示:模块名最好是以域名开头,比如 flysnow.org/gotest,这样可以很大程度上保证模块名的唯一,不至于和其他模块重名。
使用第三方模块
模块化为什么能提高开发效率? 最重要的原因是复用了现有模块,Go语言也不例外。Github上也有很多开源的Go语言项目,它们都是一个个独立的模块,也可以被我们直接使用,提高开发效率,比如Web框架 gin-gonic/gin 。
众所周知,在使用第三方模块前,需要先设置 Go代理,也就是GOPROXY,这样我们可以获取第三方模块了。 更推荐 goproxy.io这个代理,非常好用,速度也很快。要使用这个代理,需要进行如下设置:
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
实际开发中,除了三方模块,还有自己开发的模块,放在 GitLab上,这是要把公司的Git代码库域名排除在 GOPROXY,为此Go语言提供了GOPRIVATE 这个环境变量帮我们达到目的。通过如下命令设置:
# 设置不走 proxy 的私有仓库,多个用逗号分隔 (可选)
go env -w GOPRIVATE=*.corp.example.com
// 实际使用时要改成公司私有仓库域名
一切都准备好就可以使用第三方模块了,加入我们要使用Gin框架,首先需要安装它,通过如下命令安装:
go get -u github.com/gin-gonic/gin
// 安装成功后,就可以像 Go语言的标准包一样,通过 import 命令导入到项目中。如下所示:
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main(){
fmt.Println("abc")
r := gin.Default()
r.Run()
}
这段代码无法编译通过,因为还没有同步Gin这个模块的依赖,也就是没有添加到go.mod文件中。通过如下命令可添加缺失的模块:
go mod tidy
// 通过这个命令,可以把缺失的模块添加进来,同时也可以移除不再需要的模块。我们不用手动修改 go.mod 文件,通过 Go语言的工具链比如 go mod tidy,就可以帮我们自动的维护、自动添加或者修改 go.mod文件
总结:
在Go语言中,包是同一目录中,编译在一起的源文件的集合。包里面有函数、类型、变量和 常量,不同包之间的调用,必须要首字母大写才可以。
而模块又是相关包的集合,它里面包含了很多为了实现该模块的包,并且还可以通过模块的方式,把已经完成的模块提供给其他项目使用,达到了代码复用、研发效率提高的目的。
所以对于项目来说。它具有模块->包->函数类型这样三层结构,同一个模块中,可以通过包组织代码,达到代码复用的目的;在不同模块中,就需要通过模块的引入,达到这个目的。
编程届有个谚语:不要重复造轮子,使用现成轮子,可以提高开发效率,降低Bug率。Go语言提供的模块、包这些能力,就可以很好的使用现有轮子,在多人协作开发中,更好的提高工作效率。