在前面系列文章中,我们对 Go 的基础语法和一些简单的特性进行介绍,如数据类型、容器等。本文开始,我们将对 Go 中的一些高级特性进行介绍,包括包管理、反射、并发等。
代码的高复用性是优秀代码必备的品质,而 Go 的包管理就为我们封装模块和复用代码提供了强有力的帮助。
Go 是一门静态强类型语言,在程序编译的过程中会把变量的反射信息如字段类型、类型信息等写入可执行文件中。在程序执行的过程中,虚拟机会加载可执行文件中变量的反射信息,并提供接口用于在运行时获取和修改能力。
Go 支持两种并发形式,一种是我们常见的共享内存并发模型和 Go 推荐使用的 CSP (顺序进程通信) 并发模型。Go 使用了一种特殊的 MPG 线程实现模型,使得可以原生态支持并发,大大提供了程序的执行效率。
本系列文章,我将会进一步加深对 Go 语言的讲解,更一步介绍 Go 中的包管理、反射和并发等高级特性,本文将会介绍 Go 包依赖管理相关的应用实践。
Go 的代码复用很大程度依赖于包基础上,而包管理很大程度依赖于 GOPATH。Go 的包管理一直饱受诟病,不过自 1.11 版本发布 Go Modules 以来已经出现很大程度的改善。本文我们将初步了解 Go 的包管理。
与大多数的编程语言一致,Go 中同样存在包的定义,我们可以通过 package 关键字定义一个包。如下代码所示:
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
我们通过 package 关键字定义了 main 包,在 Go 中规定主函数 #main 必须位于 main 包下。引入包可以使用 import 关键字,引入多个包可以将它们放置在括号内一块引入,如下所示:
import (
"fmt"
"os")
在同一个包内定义的 func、type、变量、常量,在该 package 下的所有文件下的代码都可以随意访问,属于包内公开。我们在 main 目录下新建一个 hello.go 文件,在里面添加一个 #sayHello 的函数,代码如下所示:
package main
import "fmt"
func sayHello() {
fmt.Println("Hello World")
}
它和 main.go 同属于 main 包下,我们可以 main.go 中直接使用 #sayHello 函数,代码如下所示:
package main
func main() {
sayHello()
}
由于我们需要同时编译 main.go 和 hello.go 文件,在 main 目录下执行以下命令:
go run main.go hello.go
即可以在命令行输出预期的 "Hello World" 字段。
如果func、type、变量、常量位于不同的包下,就需要将它们名称的首写字母大写,表示它们是公开可访问的。对结构体下的字段,如果想要在包外访问,也需要将变量名首字母大写。
我们在 main 目录同级创建一个新的目录 compute,在 compute目录下新建 add.go 文件,add.go 文件的代码如下所示:
package compute
type AddOperator interface {
/**
* 算术相加
*/
Add() interface{}
}
type IntParams struct{
P1 int // 加数
P2 int // 被加数
}
func (params *IntParams) Add() interface{} {
return params.P1 + params.P2
}
我们通过 package compute 将 add.go 归属于 compute 包下;定义了 AddOperator 接口,接口中只有一个方法 #Add 用于进行算数相加操作;同时定义了 IntParams 结构体用于实现 AddOperator#Add,将 IntParams 内包含的两个整数进行相加并返回结果。
可以注意到,add.go 中的接口、函数、结构体以及结构体下的字段的首字母都是大写的,这表示它们都是公开的,可以在包外访问到。接着我们修改一下 main 包下的 main 函数,让它引用并使用 compute 包下定义的结构体和函数,代码如下所示:
package main
import (
"ch4-feature/compute"
"fmt"
)
func main() {
params := &compute.IntParams{
P1:1,
P2:2,
}
fmt.Println(params.Add())
}
我们熟悉在在 import 引入了 ch4-feature/compute 包,接着在 main 函数中直接声明并初始化了 IntParams,最后还调用了 #Add 方法返回结果,在 main 目录下的命令行中执行:
go run main.go
Go 就会为我们同时编译 main.go 和 compute 包,执行 main 函数并返回预期的结果 3。
本文主要介绍了 Go 语言的包依赖管理。与其他语言一样,Go 语言通过 package 关键字定义一个包。在同一个包内定义的func、type、变量、常量,在该 package下的所有文件下的代码都可以随意访问,属于包内公开。我们通过 package 关键字定义 main 包,在 Go 中规定主函数 #main 必须位于 main 包下。
下一篇文章将会继续介绍 GOPATH 相关的内容。