Golang中的go mod以及Golang包详解
1.Golang中包的介绍和定义
包(package)是多个Go源码的集合,是一种高级的代码复用方案,Go语言为我们提供了很多内置包,如fmt,strconv,sort,errors,time,encoding/json,os,io等。
Golang中的包可以分为三种:1.系统内置包 2.自定义包 3.第三方包
系统内置包:Golang语言给我们提供的内置包,引入后可直接使用,如fmt,strconv,sort,errors,time,encoding/json,os,io等。
自定义包:开发者自己写的包
第三方包:属于自定义包的一种,需要下载安装到本地后才可以使用,如前面用到的"github.com/shopspring/decimal"包解决float精度丢失问题
2.Golang包管理工具 go mod
在Golnag 1.11 版本之前如果要自定义包,必须把项目放在GOPATH目录。Go1.11版本之后无需手动配置环境变量,使用go mod管理项目,也不需要非得把项目放到GOPATH指定目录下,可以再磁盘任意位置新建项目,Go1.13以后可以彻底不要GOPATH 了。
1.go mod init 初始化项目
实际项目开发中,首先在项目目录中用go mod命令生成一个go.mod文件管理项目的依赖。
比如我们的项目文件放在了Demo16这个文件夹,这个时候我们需要在Demo16文件夹里面使用go mod命令生成一个 go.mod文件
go mod init 项目名称
在Demo16下建calc文件夹,在calc文件夹下建calc.go文件
package calc
在Demo16下建main.go文件作为程序主入口,引入calc包
package main
import (
"Demo16/calc"
"fmt"
)
3.Golang中自定义包
包(package)是多个Go源码的集合,一个包可以简单理解为一个存放多个.go文件的文件夹。该文件夹下面的所有go文件都要在代码第一行添加如下代码,声明该文件归属的包。
package 包名
注意事项:
- 一个文件夹下面直接包含的文件只能归属一个package,同样一个package的文件不能在多个文件夹下。
- 包名可以不和文件夹名字一样,包名不能包含 - 符号
- 包名为main的包为应用程序的入口包,这种包编译后会得到一个可执行的文件,而编译不包含main包的源代码则不会得到可执行的文件
1.定义一个包
如果想在一个包中引用另外一个包里的标识符(如变量,常量,类型,函数等)时,该标识符
2.导入一个包
单行导入
单行导入的格式如下:
import "包1"
import "包2"
多行导入
多行导入的格式如下:
import (
"包1"
"包2"
)
匿名导入包
如果只希望导入包,而不使用包内部的数据时,可以使用匿名导入包。具体的格式如下:
import _ "包的路径"
匿名导入的包与其他方式导入的包一样都会被编译到可执行文件中。
自定义包名
在导入包名的时候,可以为导入的包设置别名。通常用于导入的包名太长或者导入的包名存在冲突的情况。具体语法格式如下:
import 别名 "包的路径"
4.Golang中init()初始化函数
init()函数介绍
在Go语言程序执行时导入包语句会自动触发包内部init函数的调用。需要注意的是:init()函数没有参数也没有返回值。init()函数在程序运行时自动被调用执行,不能再代码中主动调用它。
包初始化执行的顺序如下图所示:
init函数执行顺序
Go语言包会从main包开始检查其导入的所有包,每个包中又可能导入了其他的包。Go编译器由此构建出一个树状的包引用关系,再根据引用顺序决定编译顺序,依次编译这些包的代码。
在运行时,被最后导入的包会最先初始化并调用其init()函数,如下图所示
5.Golang中使用第三方包
我们可以在 https://pkg.go.dev/ 查找常见的golang第三方包
1.找到需要下载安装的第三方包的地址
比如前面用到的解决float精度损失的包decimal
https://github.com/shopspring/decimal
2.安装包
第一种方法:go get 包名称 (全局)
go get github.com/shopspring/decimal
第二种方法:go mod download (全局)
go mod download
依赖包会自动下载到$GOPATH/pkg/mod,多个项目可以共享缓存的mod,注意使用go mod download的时候首先需要在项目里面引入第三方包
第三种方法: go mod vendor 将依赖复制到当前项目的vendor下 (本项目)
go mod vendor
注意:使用go mod vendor 的时候首先需要在项目里面引入第三方包
3.看文档使用包
包安装完毕后,可以看文档使用安装的包
代码:
Demo16/main.go
package main
import (
// "Demo16/calc"
"fmt"
// "Demo16/tools"
// T "Demo16/tools"//使用T作为tools包的别名
// _ "Demo16/tools"
// "github.com/shopspring/decimal"
)
//main包中init函数优先于main函数
func init() {
fmt.Println("main init ...")
}
func main() {
// sum := calc.Add(10, 2)
// fmt.Println(sum)//12
// fmt.Println(calc.Age)//公有变量
// fmt.Println(calc.aaa)//cannot refer to unexported name calc.aaa
//调用tools包里的方法
// a := tools.Mul(2, 3)
// fmt.Println(a)//6
// tools.PrintInfo()//print information
// tools.SortIntAsc()//按照升序对int切片排序
//同一个包里不同文件下的方法不能重复
// b := T.Mul(3,4)
// fmt.Println(b)//12
//测试init方法执行顺序
// tools.PrintInformation()
// quantity := decimal.NewFromInt(3)
// fmt.Println(quantity)
}
Demo16/calc/calc.go
package calc
import "fmt"
var aaa = "私有变量"//首字母小写表示私有
var Age = "公有变量"
func init() {
fmt.Println("calc init...")
}
func Add(x, y int) int {//首字母大写,公有方法
return x + y
}
func sub(x, y int) int {//首字母小写,私有方法
return x - y
}
Demo16/tools/tools.go
package tools
import "fmt"
import _ "Demo16/calc"
func init() {
fmt.Println("tools init...")
}
func PrintInformation() {
fmt.Println("tools print...")
}
Demo16/tools/calc.go
package tools
func Mul(x, y int) int {
return x * y
}
Demo16/tools/sort.go
package tools
import "fmt"
func SortIntAsc() {
fmt.Println("按照升序对int切片排序")
}
Demo16/tools/test.go
package tools
import "fmt"
func PrintInfo() {
fmt.Println("print information")
}
func init() {
fmt.Println("test init...")
}