Go modules工程

使用go module创建出来的就是不同,因为自带go.mod文件

go mod文件就像maven一样保存包结构

go mod


  • go1.11版本开始支持go modules
  • 包的存放路径为{GOPATH}windows默认在 %USERPROFILE%\go (C:\Users\xxx\go)
  • go.mod 记录依赖包的名字以及版本号等信息
  • go.sum 记录依赖包的校验信息
手动使用 go mod 初始化项目:
mkdir go-demo
cd go-demo
go mod init go-demo #生成go.mod和go.sum
go env -w GOPROXY="https://goproxy.cn,direct"

Go modules工程_第1张图片

Go modules工程_第2张图片

可以看到gin的包名和版本号。然后下面是gin的依赖,一层依赖一层。

Go modules工程_第3张图片

Go modules工程_第4张图片

Go modules工程_第5张图片

Go modules工程_第6张图片

这个是和go mod里面完全对齐的,其实就是MD5校验。

由于导入的包有多种版本,最新版本可能导致和原来版本有冲突需要修改源代码,那么这种情况直接在go.mod里面去修改,依赖不需要修改。

Go modules工程_第7张图片

修改版本之后,在main里面导入该版本的包即可。

Go modules工程_第8张图片

或者

下载未安装但使用到的包
修改依赖包版本:修改 go.mod 中依赖包的版本号后,执行 go mod tidy 即可
go mod tidy

工作目录


在开始Go Modules工程前,我们需要介绍下GOPATH工程, 它虽然不怎么好用,但是他是你1.11版本之前的唯一选择

GOPATH 工程


在Go 1.1 ~ 1.11 (2013/05 ~ 2018/08), 都是使用GoPATH工程结构, 直到现在依然有很多老的项目依然使用这种方式

特征

安装部署go环境,使用go进行开发的时候强制被要求要设置GOPATH(当然安装过程中也会默认指定$GOPATH=~/go)。 要在GOPATH路径下新建 src bin pkg文件夹, 因此一个GOPATH工程它的结构是这样的: 

Go modules工程_第9张图片

go env GOPATH
E:\Golang
$GOPATH
├── bin  # 存储go编译生成的二进制可执行文件,一般会把该路径配置到PATH中,PATH=$PATH:$GOPATH/bin
├── pkg  # 存储预编译的目标文件,以加快后续的编译速度 
└── src  # 存储Go的源代码,一般以$GOPATH/src/github.com/foo/bar的路径存放

编译时的依赖包查找机制


 只要我们的代码里面出现了import 关键字, 就代表我们需要依赖其他的源代码,比如

import "fmt"
import "github.com/jinzhu/gorm"

这个时候 编译器就需要搜索这些源码的存放位置, 搜索顺序为:

  • 优先使用vendor目录下面的包
  • 如果vendor下面没有搜索到,再搜索$GOPATH/src下面的包
  • 如果GOPATH下面没有搜索到,那么搜索GOPATH下面没有搜索到,那么搜索GOROOT/src下面的包

比如fmt的搜索({dir}/path):

  1. vendor 无
  2. $GOPATH/src 无
  3. GOROOT/src找到,路径为(GOROOT/src找到,路径为(GOROOT/src/fmt)

比如第一天我们有这样一个代码:$GOPATH/src/day1/compile/main.go

$ cat  
package main

import "day1/compile/pkg"

func main() {
        pkg.Demo()
}

搜索顺序({dir}/path):

  1. vendor 无
  2. GOPATH/src找到,路径为(GOPATH/src找到,路径为(GOPATH/src/day1/compile/pkg)

缺陷

  1. 无法控制依赖版本 $GOROOT/src 是我们安装Go时自带的, 和你Go的版本有关系, 但是比如其他的依赖, 比如"github.com/jinzhu/gorm", 它会直接拉取放到我们的$GOPATH/src下面, 无版本概念, 无法控制导入包的版本

  2. 污染我们工作目录,会在$GOPATH/src下面看到我们所有的依赖, 并不是我单个项目的依赖 比如下面:

Go modules工程_第10张图片

Go Modules 工程


GOPATH工程, 受限于GOPATH目录的约束, 并且无法控制版本, 终于Go 在1.11版本开始推出Go Modules

Go1.13开始不再推荐使用GOPATH。意思就是说你可以在任何路径下存放你的Go源码文件, 不用再像以前一样非得放到$GOPATH/src中。 每一个go项目 都是一个 Module

Go1.16版本 推荐生成环境可用

特征

该工程目录的根目录下有一个go.mod的文件,主要用于描述模块的名称和依赖,比如本项目:

module gitee.com/infraboard/go-course    // 模块名称

go 1.16

如何启用

GO111MODULE 这个环境变量是用来作为使用Go Modules 的开关。可以说这个变量是历史产物,很有肯能会在将来Go的新版本中去除掉

GO111MODULE有3个值可供设置:

GO111MODULE="auto" # 只要项目包含了go.mod 文件的话就启用Go modules, 在Go1.11-1.14 中是默认值
GO111MODULE="on"   # 启用Go Modules
GO111MODULE="off"  # 禁用Go Modules, 对老的项目进行兼容

编译时的依赖包查找机制

开启模块支持,项目编译时会忽略GOPATHvendor文件夹只根据go.mod下载所需要的依赖同时该依赖会被下载到 $GOPATH/pkg/mod 目录下如下是我go mod管理的依赖

$ ls /e/Golang/pkg/mod/
9fans.net             [email protected]                            gopkg.in                          rsc.io
cache                 [email protected]  [email protected]               sigs.k8s.io
cloud.google.com      [email protected]  [email protected]+incompatible  sourcegraph.com
dmitri.shuralyov.com  go.uber.org                                         honnef.co                         vitess.io
github.com            golang.org                                          k8s.io
go.etcd.io            gonum.org                                           modernc.org
go.mongodb.org        google.golang.org                                   mvdan.cc
  • 当前目录,模块名称打头的包, 比如 "gitee.com/infraboard/go-course/day1/compile/pkg", 相对于 $workspace/day1/compile/pkg
  • 如果未找到,再去$GOPATH/pkg/mod 下搜索
  • 如果未找到, 再去$GOROOT/src 下搜索

Go Modules模式下并不兼容GOPATH模式, 之前在GOPATH下运行的包,在GOMODULE模式下无法运行,比如: 

$ go run main.go
main.go:3:8: package day1/compile/pkg is not in GOROOT (C:\Program Files\Go\src\day1\compile\pkg)

 因此如果你有GOPATH的项目需要维护是,建议将GO111MODULE设置为auto

go env -w GO111MODULE=auto

如何创建一个Go Modules工程


  1. 新建一个目录(不要在GOPATH下创建) 
mkdir {your_project_workspace}

2.使用go mod 初始化工程

你当前的目录仅仅是一个目录, 并不是一个go mod工程, 我们通过go mod init {name} 将你的目录初始化为一个go mod工程

cd {your_project_workspace}
go mod init {your_project_workspace}

3.打开工程

使用vscode打开你的{your_project_workspace}文件夹, 然后你就可以在该工程下面写程序了

 引入Go Modules后, 最好不要在一个文件下面放2个main.go,我们讲采用go test的方式快速演示功能,比如:

Go modules工程_第11张图片

关键点:

  • 文件名命名要求: {pkg_name}_test.go
  • 函数命名要求: 大写Test开头
  • 函数参数: (t *testing.T)

比如 variable/variable_test.go

package variable

import (
    "testing"
)

func TestValueRef(t *testing.T) {
    i := "this is a"
    j := &i
    *j = "this is j"
    t.Log(i, *j)
}

扩展 编写测试


go在语言层面是支持单元测试的,因为提供了单元测试包,这个包其实就是testing包。主要使用的是两个,一个是功能测试,一个是性能测试。

单元测试一般都是函数级别的

在go语言当中编写测试,这个类似于java的junit。

编写测试程序
  1. 源码⽂件一定以 _test.go 结尾:xxx_test.go
  2. 测试⽅法名一定以Test 开头:func TestXXX(t *testing.T) {…}
  3. 参数是固定的,不需要修改  t *testing.T

大写字母开头的方法也代表包外可以访问,但是对于测试来说没太多意义,但是如果是test方法那么必须以方法名称必须以大写的test开头。

实现 Fibonacci 数列

1, 1, 2, 3, 5, 8, 13, ….  
func TestFibList(t *testing.T){

	var(
		a  = 1
		b  = 1
	)

	t.Log(a)
	for i := 0;i <= 5;i ++{
		sum := a + b
		t.Log(sum)
		a = b
		b = sum
	}
}


=== RUN   TestFibList
    my_test.go:134: 1
    my_test.go:137: 2
    my_test.go:137: 3
    my_test.go:137: 5
    my_test.go:137: 8
    my_test.go:137: 13
    my_test.go:137: 21
--- PASS: TestFibList (0.00s)

包的使用


Go modules工程_第12张图片 要测试包里面的函数

Go modules工程_第13张图片

Go modules工程_第14张图片

你可能感兴趣的:(Golang,包管理,函数,golang)