Go 包相关
包的作用
Go
语言中的包是源码的集合,是一种高级的代码复用方案。
在Go
语言中拥有很多自带的包,如fmt
、os
等。
我们也可以进行一个自定义的包。
定义包
一个文件只能归属于一个包。
如main
旧是一个可执行文件包,编译main
包会得到一个可执行文件,如果是非main
包则不会得到一个可执行文件。
包的命名不可以和文件夹名字相同,并且不可含有特殊符号。
如下的定义一个test
包。
注意:一个main包不可被其他文件进行导入
package test
import (
"fmt"
)
// F1 是一个公开的方法
func F1(){
fmt.Println("test包中的F1")
}
可见性
在包内,如果标识符首字母为大写则代表该标识符是对外可见的。
反之则是该包的私有标识符。
package test
import (
"fmt"
)
// F1 是一个公开的方法
func F1(){
fmt.Println("test包中的F1")
}
// Person 是一个公开的结构体
type Person struct{
name string // name是一个私有的结构体字段
}
导入包
注意事项
导入包时使用import
关键字进行导入。同时它有一些以下的注意事项:
import导入语句通常放在文件开头包声明语句的下面。
导入的包名需要使用双引号包裹起来,同时包名则是文件夹的名称。
包名是从$GOPATH/src/后开始计算的,使用/进行路径分隔。
Go语言中禁止循环导入包。
单行导入
单行导入是使用较少的导入方式,格式如下:
import "包1"
import "包2"
多行导入
多行导入使用括号进行包裹,可在一个import
下导入多个包,格式如下:
import (
"包1"
"包2"
)
别名导入
我们可以为导入的包取一个自定义名字,格式如下:
import 别名 "包的路径"
或者在多行导入时这样使用,内置的包会放在上面,自定义或第三方包会放在下面。
import (
"内置包"
别名 "第三方包路径"
)
匿名导入
匿名导入的意义在于我们只导入这个包,但是并不会调用其中的某些方法。
如链接数据库时就会使用到匿名导入。
匿名导入的包与其他方式导入的包一样都会被编译到可执行文件中。
语法如下:
import _ "包的路径"
示例演示
目录结构如下:
- bin
- pkg
- src
- yunya.com
- module
- test.go // 这是一个自定义包
- main.go // 启动文件
我们想在main.go
中使用test.go
中的功能,则可进行如下的导入:
package main
import "fmt"
import "yunya.com/module" // 注意,包是所属文件夹的名称
func main() {
test.F1()
fmt.Println("执行fmt中的Println")
}
init函数
函数介绍
init()
函数是一个go
文件作为包时将自动触发的一个函数(如果没有该函数则忽略)。
init()
函数没有参数也没有返回值, init()
函数在程序运行时自动被调用执行,不能在代码中主动调用它。
如下所示:
test.go
package test
import (
"fmt"
)
// F1 是一个公开的方法
func F1(){
fmt.Println("test包中的F1")
}
// Person 是一个公开的结构体
type Person struct{
name string // name是一个私有的结构体字段
}
func init(){
fmt.Println("自动执行我啦")
}
当调用该包时,自动执行init
,打印结果如下:
package main
import "fmt"
import "yunya.com/module" // 注意,包是所属文件夹的名称
func main() {
test.F1()
fmt.Println("执行fmt中的Println")
}
// 自动执行我啦
// test包中的F1
// 执行fmt中的Println
main与init
如果一个go
文件是一个main
包,同时在其中声明了那么main()
函数与init()
函数执行谁先谁后呢?
结果如下:
package main // 单独执行,main包不可被导入
import (
"fmt"
)
func main() {
fmt.Println("执行main")
}
func init() {
fmt.Println("执行init")
}
// 执行init
// 执行main
执行顺序
Go
语言包会从main
包开始检查其导入的所有包,每个包中又可能导入了其他的包。
Go
编译器由此构建出一个树状的包引用关系,再根据引用顺序决定编译顺序,依次编译这些包的代码。
在运行时,被最后导入的包会最先初始化并调用其init()
函数, 如下图示:
多个main
当一个项目下有多个main
时,则不用进行导入。依次执行即可,在编译时会自动将其整合成一个可执行文件。
注意:多个main时需要防止变量冲突的问题,同时多个main中没有可见性这一说法,由于会整合成一个可执行文件,所以它们彼此之间都是可见的
目录结构如下:
- bin
- pkg
- src
- yunya.com
- start.go // 启动文件 main包
- s1.go // main包
- s2.go // main包
具体代码如下:
// -- start中的内容
package main
import (
"fmt"
)
func main() {
fmt.Println(s1)
fmt.Println(s2)
}
// -- s1中的内容
package main
var s1 = string("s1变量")
// -- s2中的内容
package main
var s2 = string("s2变量")
执行命令时,使用以下命令:
go run start.go s1.go s2.go
或者直接使用以下命令,编译该文件夹下所有的main
包go
文件进行整合处理:
go build