Go语言中支持模块化的开发理念,在Go语言中使用包(package)
来支持代码模块化和代码复用。一个包是由一个或多个Go源码文件(.go结尾的文件)组成,是一种高级的代码复用方案,Go语言为我们提供了很多内置包,如fmt
、os
、io
等。
例如,在之前频繁使用了fmt
这个内置包。
package main
import "fmt"
func main(){
fmt.Println("Hello world!")
}
上面短短的几行代码就涉及到了如何定义包以及如何引入其它包两个内容,接下来我们依次介绍一下它们。
我们可以根据自己的需要创建自定义包。一个包可以简单理解为一个存放.go
文件的文件夹。该文件夹下面的所有.go
文件都要在非注释的第一行添加如下声明,声明该文件归属的包。
package packagename
其中:
-
符号,最好与其实现的功能相对应。另外需要注意一个文件夹下面直接包含的文件只能归属一个包,同一个包的文件不能在多个文件夹下。包名为main
的包是应用程序的入口包,这种包编译后会得到一个可执行文件,而编译不包含main
包的源代码则不会得到可执行文件。
在同一个包内部声明的标识符都位于同一个命名空间下,在不同的包内部声明的标识符就属于不同的命名空间。想要在包的外部使用包内部的标识符就需要添加包名前缀,例如fmt.Println("Hello world!")
,就是指调用fmt
包中的Println
函数。
如果想让一个包中的标识符(如变量、常量、类型、函数等)能被外部的包使用,那么标识符必须是对外可见的(public)。在Go语言中是通过标识符的首字母大/小写来控制标识符的对外可见(public)/不可见(private)的。在一个包内部只有首字母大写的标识符才是对外可见的。
例如我们定义一个名为demo
的包,在其中定义了若干标识符。在另外一个包中并不是所有的标识符都能通过demo.
前缀访问到,因为只有那些首字母是大写的标识符才是对外可见的。
package demo
import "fmt"
// 包级别标识符的可见性
// num 定义一个全局整型变量
// 首字母小写,对外不可见(只能在当前包内使用)
var num = 100
// Mode 定义一个常量
// 首字母大写,对外可见(可在其它包中使用)
const Mode = 1
// person 定义一个代表人的结构体
// 首字母小写,对外不可见(只能在当前包内使用)
type person struct {
name string
Age int
}
// Add 返回两个整数和的函数
// 首字母大写,对外可见(可在其它包中使用)
func Add(x, y int) int {
return x + y
}
// sayHi 打招呼的函数
// 首字母小写,对外不可见(只能在当前包内使用)
func sayHi() {
var myName = "七米" // 函数局部变量,只能在当前函数内使用
fmt.Println(myName)
}
同样的规则也适用于结构体,结构体中可导出字段的字段名称必须首字母大写。
type Student struct {
Name string // 可在包外访问的方法
class string // 仅限包内访问的字段
}
要在当前包中使用另外一个包的内容就需要使用import
关键字引入这个包,并且import语句通常放在文件的开头,package
声明语句的下方。完整的引入声明语句格式如下:
import importname "path/to/package"
其中:
一个Go源码文件中可以同时引入多个包,例如:
import "fmt"
import "net/http"
import "os"
当然可以使用批量引入的方式。
import (
"fmt"
"net/http"
"os"
)
当引入的多个包中存在相同的包名或者想自行为某个引入的包设置一个新包名时,都需要通过importname
指定一个在当前文件中使用的新包名。例如,在引入fmt
包时为其指定一个新包名f
。
import f "fmt"
这样在当前这个文件中就可以通过使用f
来调用fmt
包中的函数了。
f.Println("Hello world!")
如果引入一个包的时候为其设置了一个特殊_
作为包名,那么这个包的引入方式就称为匿名引入。一个包被匿名引入的目的主要是为了加载这个包,从而使得这个包中的资源得以初始化。 被匿名引入的包中的init
函数将被执行并且仅执行一遍。
import _ "github.com/go-sql-driver/mysql"
匿名引入的包与其他方式导入的包一样都会被编译到可执行文件中。
需要注意的是,Go语言中不允许引入包却不在代码中使用这个包的内容,如果引入了未使用的包则会触发编译错误。
基于Nginx+Supervisord+uWSGI+Django1.11.1+Python3.6.5构建