Go通过包(package)的⽅式来组织和管理源码,任何⼀个源码必须属于⼀个包,更其他语言的包功能类似,包的作用把相关功能的代码组织在一个包文件下,包名在源文件中第一行通过关键字package指定,包名一般建议小写
package 包名称
每个目录下面可以有多个.go文件,这些文件只能属于同一个包。同一个包下的不同.go文件相互之间可以直接引用变量和函数,所以这些文件中定义的全局变量和函数不能重名。
包导入
导入包需要将包名称用引号,导入包主要可分为两种方式,
单行导入
import "fmt"
import "sync"
多行导入
import(
"fmt"
"sync"
)
main包
可执⾏程序入口的的包名必须为main,而且在main包中必须且只能有一个main()函数,main()函数就是应用程序运行开始入口
package main
import "fmt"
func main() {
fmt.Println("hello golang")
}
⾃定义包
⽤户可以写⾃定义包,⾃定义包编译成静态库,一般建议自定义包的名称就是文件目录的名称。
package utils
import (
"crypto/md5"
"encoding/hex"
)
func EncodeMD5(value string) string {
m := md5.New()
m.Write([]byte(value))
return hex.EncodeToString(m.Sum(nil))
}
应用自定义包的函数,导出变量或函数。⾸字⺟⼤写表示可导出,⼩写表示私有。不能被外部的包访问
package main
import (
"fmt"
"github.com/baxiang/go-note/utils"
)
func main() {
fmt.Println(utils.EncodeMD5("hello golang"))
}
注意 如果对外提供的函数 需要首字母大写,否则自定义包函数是如无法被其他包引用的
使用别名
在一些场景下,我们可能需要对导入的包进行重新命名,比如
- 我们导入了两个具有同一包名的包时产生冲突,此时这里为其中一个包定义别名
import (
"crypto/rand"
mrand "math/rand" // 将名称替换为mrand避免冲突
)
- 我们导入了一个名字很长的包,为了避免后面都写这么长串的包名,可以这样定义别名
import hw "helloworldtestmodule"
- 防止导入的包名和本地的变量发生冲突,比如 path 这个很常用的变量名和导入的标准包冲突。
import pathpkg "path"
包的初始化
每个包都允许有一个 init
函数,当这个包被导入时,会执行该包的这个 init
函数,做一些初始化任务。
对于 init
函数的执行有两点需要注意
- init()函数不能被其他函数调用,init 函数优先于 main 函数之前会自动执行。
- 不同包的init()函数按照包导入的依赖关系决定该函数的执行顺序比如,有这样一个包引用关系:main→A→B→C,那么初始化顺序为
C.init→B.init→A.init→main
包的匿名导入
当我们导入一个包时,如果这个包没有被使用到,在编译时,是会报错的。
但是有些情况下,我们导入一个包,只想执行包里的 init
函数,来运行一些初始化任务,此时怎么办呢?
可以使用匿名导入,用法如下,其中下划线为空白标识符,并不能被访问
// 注册一个PNG decoder
import _ "image/png"
由于导入时,会执行 init 函数,所以编译时,仍然会将这个包编译到可执行文件中。
参考
https://github.com/iswbm/GolangCodingTime/blob/master/source/c03/c03_04.md