1.包的命名
go语言的包的命名,遵循简洁、小写、和go文件所在目录同名的原则,这样就便于我们引用,书写以及快速定位查找。比如go自带的http这个包,它这个http目录下的所有go文件都属于这个http包,所以我们使用http包里的函数、接口的时候,导入这个http包就可以了。
package main
import "net/http"
func main() {
http.ListenAndServe("127.0.0.1:80",handler);
}
从这个例子可以看到,我们导入的是net/http
,这在go里叫做全路径,因为http包在net里面,net是最顶级的包,所以必须使用全路径导入,go编译程序才能找到http这个包,和我们文件系统的目录路径是一样的。
对于自己或者公司开发的程序而言,我们一般采用域名作为顶级包名的方式,这样就不用担心和其他开发者包名重复的问题了,比如我的个人域名是www.flysnow.org
,那么我自己开发的go程序都以flysnow.org
作为全路径中的最顶层部分,比如导入我开发的一个工具包:
package main
import "flysnow.org/tools"
2.main 包
当把一个go文件的包名声明为main
时,就等于告诉go编译程序,我这个是一个可执行的程序,那么go编译程序就会尝试把它编译为一个二进制的可执行文件。
一个main
的包,一定会包含一个main()
函数,这种我们也不陌生,比如C和Java都有main()
函数,它是一个程序的入口,没这个函数,程序就无法执行。
在go语言里,同时要满足main
包和包含main()
函数,才会被编译成一个可执行文件。
3.导入包
要想使用一个包,必须先导入它才可以使用,Go语言提供了import
关键字来导入一个包,这个关键字告诉Go编译器到磁盘的哪里去找要想导入的包,所以导入的包必须是一个全路径的包,也就是包所在的位置。
import "fmt"
这就表示我们导入了fmt
包,也就等于告诉go编译器,我们要使用这个包下面的代码。如果要导入多个包怎么办呢?Go语言还为我们提供的导入块。
import (
"net/http"
"fmt"
)
使用一对括号包含的导入块,每个包独占一行
对于多于一个路径的包名,在代码中引用的时候,使用全路径最后一个包名作为引用的包名,比如net/http
,我们在代码使用的是http
,而不是net
4.命名导入
我们知道,在使用import
关键字导入包之后,我们就可以在代码中通过包名使用该包下相应的函数、接口等。如果我们导入的包名正好有重复的怎么办呢?针对这种情况,Go语言可以让我们对导入的包重新命名,这就是命名导入。
package main
import (
"fmt"
myfmt "mylib/fmt" //命名导入
)
func main() {
fmt.Println()
myfmt.Println()
}
如果没有重新命名,那么对于编译器来说,这两个fmt
它是区分不清楚的。重命名也很简单,在我们导入的时候,在包名的左侧,起一个新的包名就可以了。
Go语言规定,导入的包必须要使用,否则会包编译错误
但是有时候,我们需要导入一个包,但是又不使用它,按照规则,这是不行的,为此Go语言给我们提供了一个空白标志符_
,只需要我们使用_
重命名我们导入的包就可以了
package main
import (
_ "mylib/fmt"
)
5.包的init函数
每个包都可以有任意多个init函数,这些init函数都会在main函数之前执行。init函数通常用来做初始化变量、设置包或者其他需要在程序执行前的引导工作。比如上面我们讲的需要使用_
空标志符来导入一个包的目的,就是想执行这个包里的init函数。
我们以数据库的驱动为例,Go语言为了统一关于数据库的访问,使用databases/sql
抽象了一层数据库的操作,可以满足我们操作MYSQL、Postgre等数据库,这样不管我们使用这些数据库的哪个驱动,编码操作都是一样的,想换驱动的时候,就可以直接换掉,而不用修改具体的代码。
这些数据库驱动的实现,就是具体的,可以由任何人实现的,它的原理就是定义了init函数,在程序运行之前,把实现好的驱动注册到sql包里,这样我们就使用使用它操作数据库了
package mysql
import (
"database/sql"
)
func init() {
sql.Register("mysql", &MySQLDriver{})//初始化mysql驱动
}
因为我们只是想执行这个mysql包的init方法,并不想使用这个包,所以我们在导入这个包的时候,需要使用_
重命名包名,避免编译错误。
import "database/sql"
import _ "github.com/go-sql-driver/mysql"//初始化mysql驱动
db, err := sql.Open("mysql", "user:password@/dbname")
看非常简洁,剩下针对的数据库的操作,都是使用的database/sql
标准接口,如果我们想换一个mysql的驱动的话,只需要换个导入就可以了,灵活方便,这也是面向接口编程的便利。