包的管理使用
# Go语言中包的使用
Go
语言使用包(package)
这种语法元素来组织源码,所有语法可见性均定义在package
这个级别,与Java 、python
等语言相比,这算不上什么创新,但与C
传统的include
相比,则是显得“先进”了许多.
$ tree ./
./myblog
├── conf
│ └── app.conf
├── controllers
│ ├── aboutme_controller.go
│ ├── add_article_controller.go
│ ├── album_controller.go
│ ├── base_controller.go
│ ├── default.go
│ ├── delete_article_controller.go
│ ├── exit_controller.go
│ ├── home_controller.go
│ ├── login_controller.go
│ ├── register_controller.go
│ ├── show_article_controller.go
│ ├── tags_controller.go
│ ├── update_article_controller.go
│ └── upload_controller.go
├── main.go
├── models
│ ├── album_model.go
│ ├── article_model.go
│ ├── home_model.go
│ ├── tags_model.go
│ └── user_model.go
├── myblogweb
├── routers
│ └── router.go
├── static
│ ├── css
│ │ ├── blogsheet.css
│ │ └── lib
│ │ ├── highlight.css
│ │ └── login.css
│ ├── img
│ ├── js
│ │ ├── blog.js
│ │ ├── lib
│ │ │ ├── jquery-3.3.1.min.js
│ │ │ └── jquery.url.js
│ │ └── reload.min.js
│ └── upload
│ └── img
│ └── 2018
│ └── 12
│ └── 11
│ ├── 1544511378-bee2.png
├── tests
│ └── default_test.go
├── utils
│ ├── myUtils.go
│ └── mysqlUtils.go
└── views
├── aboultme.html
├── album.html
├── block
│ ├── home_block.html
│ └── nav.html
├── home.html
├── index.tpl
├── login.html
├── register.html
├── show_article.html
├── tags.html
└── write_article.html
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Go
语言的源码复用建立在包(package)
基础之上.包通过package, import, GOPATH
操作完成.
# 1、 main包
Go
语言的入口main()
函数所在的包(package)
叫main
,main
包想要引用别的代码,需要impor
t导入!
# 2、 package
src
目录是以代码包的形式组织并保存Go
源码文件的.每个代码包都和src
目录下的文件夹一一对应.每个子目录都是一个代码包.
代码包包名和文件目录名,不要求一致.比如文件目录叫
hello
,但是代码包包名可以声明为main
,但是同一个目录下的源码文件第一行声明的所属包,必须一致!
同一个目录下的所有.go
文件的第一行添加 包定义,以标记该文件归属的包,演示语法:
package 包名
包需要满足:
- 一个目录下的同级文件归属一个包.也就是说,在同一个包下面的所有文件的
package
名,都是一样的. - 在同一个包下面的文件
package
名都建议设为是该目录名,但也可以不是.也就是说,包名可以与其目录不同名. - 包名为
main
的包为应用程序的入口包,其他包不能使用.
在同一个包下面的文件属于同一个工程文件,不用
import
包,可以直接使用
包可以嵌套定义,对应的就是嵌套目录,但包名应该与所在的目录一致,例如:
// 文件:src/tools/tool.go中
package tools
// 可以被导出的函数
func FuncPublic() {
}
// 不可以被导出的函数
func funcPrivate() {
}
2
3
4
5
6
7
8
包中,通过标识符首字母是否大写,来确定是否可以被导出.首字母大写才可以被导出,视为public
公共的资源.
# 3、 import
- 要引用其他包,可以使用
import
关键字,可以单个导入或者批量导入,语法演示
A:通常导入
// 单个导入
import "package"
// 批量导入
import (
"package1"
"package2"
)
2
3
4
5
6
7
B:点操作
- 有时候会看到如下的方式导入包
import(
. "fmt"
)
2
3
这个点操作的含义就是这个包导入之后在调用这个包的函数时,可以省略前缀的包名,也就是前面调用的fmt.Println("hello world")
可以省略的写成Println("hello world")
C:起别名
- 别名操作顾名思义可以把包命名成另一个用起来容易记忆的名字.导入时,可以为包定义别名,语法演示
import (
p1 "package1"
p2 "package2"
)
// 使用时:别名操作,调用包函数时前缀变成了前缀
p1.Method()
2
3
4
5
6
D:_操作
- 如果仅仅需要导入包时执行初始化操作,并不需要使用包内的其他函数,常量等资源.则可以在导入包时,匿名导入.
这个操作经常是让很多人费解的一个操作符,请看下面这个import
import (
"database/sql"
_ "github.com/ziutek/mymysql/godrv"
)
2
3
4
_
操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init
函数.也就是说,使用下划线作为包的别名,会仅仅执行init()
.
导入的包的路径名,可以是相对路径也可以是绝对路径,推荐使用绝对路径(起始于工程根目录).
# 4、GOPATH环境变量
import
导入时,会从GO
的安装目录(也就是GOROOT
环境变量设置的目录)和GOPATH
环境变量设置的目录中,检索src/package
来导入包.如果不存在,则导入失败.GOROOT
,就是GO
内置的包所在的位置.GOPATH
,就是自己定义的包的位置.- 通常在开发
Go
项目时,调试或者编译构建时,需要设置GOPATH
指向项目目录,目录中的src
目录中的包就可以被导入了.
# 5、init() 包初始化
- 详细的介绍一下这两个函数:
init()、main()
是go
语言中的保留函数.可以在源码中,定义init()
函数.此函数会在包被导入时执行,例如如果是在main
中导入包,包中存在init()
,那么init()
中的代码会在main()
函数执行前执行,用于初始化包所需要的特定资料.例如:
包源码:
src/userPackage/tool.go
package userPackage
import "fmt"
func init() {
fmt.Println("tool init")
}
2
3
4
5
6
7
主函数源码:
src/main.go
package main
import (
"userPackage"
)
func main() {
fmt.Println("main run")
// 使用userPackage
userPackage.SomeFunc()
}
2
3
4
5
6
7
8
9
10
11
执行时,会先输出"tool init"
,再输出"main run"
.
详细的来介绍一下init()、main()
这两个函数.在go
语言中的区别如下:
相同点:
- 两个函数在定义时不能有任何的参数和返回值.
- 该函数只能由
go
程序自动调用,不可以被引用.
不同点:
init
可以应用于任意包中,且可以重复定义多个.main
函数只能用于main
包中,且只能定义一个.
两个函数的执行顺序:
- 在
main
包中的go
文件默认总是会被执行. - 对同一个
go
文件的init( )
调用顺序是从上到下的. - 对同一个
package
中的不同文件,将文件名按字符串进行“从小到大”排序,之后顺序调用各文件中的init()
函数. - 对于不同的
package
,如果不相互依赖的话,按照main
包中import
的顺序调用其包中的init()
函数. - 如果
package
存在依赖,调用顺序为最后被依赖的最先被初始化,例如:导入顺序main –> A –> B –> C
,则初始化顺序为C –> B –> A –> main
,依次执行对应的init
方法.main
包总是被最后一个初始化,因为它总是依赖别的包
- 避免出现循环
import
,例如:A –> B –> C –> A
.- 一个包被其它多个包
import
,但只能被初始化一次
- 一个包被其它多个包
# 6、管理外部包
go
允许import
不同代码库的代码.对于import
要导入的外部的包,可以使用go get
命令取下来放到GOPATH
对应的目录中去.
比如说想通过go
语言连接mysql
数据库,那么需要先下载mysql
的数据包,打开终端并输入以下命令
$ go get github.com/go-sql-driver/mysql
安装之后,就可以在gopath
目录的src
下,看到对应的文件包目录:
也就是说,对于
go
语言来讲,其实并不关心代码是内部还是外部的,总之都在GOPATH
里,任何import
包的路径都是从GOPATH
开始的;唯一的区别,就是内部依赖的包是开发者自己写的,外部依赖的包是go get
下来的.
# 扩展
- 可以通过
go install
来编译包文件. - 一个非
main
包在编译后会生成一个.a
文件(在临时目录下生成,除非使用go install
安装到$GOROOT
或$GOPATH
下,否则看不到.a
),用于后续可执行程序链接使用. - 比如
Go
标准库中的包对应的源码部分路径在:$GOROOT/src
,而标准库中包编译后的.a文
件路径在$GOROOT/pkg/darwin_amd64
下.
- 01
- AWS NAT-NetWork-Firwalld配置(一)04-09
- 02
- AWS NAT-NetWork-Firwalld配置(二)04-09
- 03
- kubernetes部署minio对象存储01-18