go代码项目管理--GOPATH与go module的比较

一、使用GOPATH进行项目管理

在Golang1.11版本以前,项目组织代码管理使用GOPATH的方式来管理。GOPATH的作用在于提供一个可以寻找.go源码的路径,它是一个工作空间的概念,可以设置多个目录。

假设现在本地硬盘上有3个Go代码工程,分别为/work/go-proj1、/work2/goproj2和~/work3/work4/go-proj3,那么GOPATH可以设置为如下内容:不同项目路径,以冒号为分割

export GOPATH=~/work/go-proj1:~/work2/goproj2:~/work3/work4/go-proj3 

经过这样的设置后,你可以在任意位置对以上的3个工程进行构建。

Go官方要求GOPATH下面需要包含三个文件夹:

  • src:存放项目源码文件,需要自己创建该目录;
  • pkg:存放源文件编译后的库文件,后缀为.a,不需要自己创建该目录,构建后自动生成;
  • bin:存放可执行文件,不需要自己创建该目录,构建后自动生成。

下面以一个实例来讲解

示例讲解

前期准备

假设我们的项目根目录为/opt/testProject,则需要把GOPATH设置成该目录:

go env -w GOPATH="/opt/testProject"

我们需要在testProject目录创建src目录,把项目源代码放入src目录中。

── testProject
    └── src
        └── getUUID
            └── hhd.go

getUUID目录里面是源代码文件,hhd.go是我们的源代码文件

package main

import (
	"fmt"
	"github.com/satori/go.uuid"
)

func main() {
	u1,_ := uuid.NewV4()
	fmt.Printf("UUIDv4: %s\n", u1)
}

项目构建

我们可以使用go build或者go install直接构建项目成一个二进制文件,如果不想生成二进制文件,则使用go run hhd.go直接运行代码。

使用go build

我们先使用go build来构建项目,注意,这里如果要构建,hhd.go需要包含的main函数,并且项目中也只有这个源文件能包含main函数,如果有其他源文件包含main函数,则无法使用go build进行构建项目。

我们直接来到项目根目录或者可以任意目录,执行一下命令进行构建代码

go build getUUID

如果构建环境没有源代码所需要的第三方包,则需要进行go get下载

image-20220807171254512

进行go get下载后,GOPATH路径下会自动生成pkg目录,把我们下载第三方库的代码编译文件放在pkg目录中,而第三方库的源代码文件则放在src目录中

image-20220807171923543

下载完第三方库后,我们在重新构建,构建成功后,便在当前目录生成可执行的二进制文件。

image-20220807172138931

./getUUID

image-20220807172224447

go build命令后面也可以不带名字,不过需要去到项目源代码文件中执行构建,生成的二进制文件名称是当前源代码文件所在目录的目录名。

这里go build后面携带getUUID,然后在任意目录执行就可以生成二进制文件的原理是,执行go build getUUID后,go编译期去自动去$GOPATH/src/getUUID目录下寻找go源代码文件,然后执行编译。如果不携带getUUID,则需要去到$GOPATH/src/getUUID目录,再执行go build

image-20220807172457607

go build后面还可以携带源代码文件名进行构建,则生成的二进制文件名称是当前源代码文件名

go build hhd.go

image-20220807172707930

我们也可以指定生成的二进制名称

go build -o getID hhd.go

image-20220807172828331

使用go install

我们直接来到项目根目录或者可以任意目录,执行以下命令进行构建代码

go install getUUID

构建成功后,会在GOPATH路径下会自动生成bin目录,然后把生成的二进制文件存放在bin目录中

image-20220807173230434

当然,go install 后面也可以不携带getUUID,但是得去getUUID目录下执行构建命令。不过要注意,go install命令不能指定生成的二进制可执行文件的名称

二、使用go module进行项目管理

前言

最早的时候,Go所依赖的所有的第三方库都放在GOPATH这个目录下面,下载的依赖包也没有版本概念,这就导致了同一个库只能保存一个版本的代码。如果不同的项目依赖无法依赖同一个第三方的库的不同版本,并且,代码开发必须在GOPATH的src目录下。这在实际开发中造成许多的问题。

go mod介绍

Go.mod是Golang1.11版本新引入的官方包管理工具用于解决之前没有地方记录依赖包具体版本的问题,方便依赖包的管理,可以理解为java中的maven。在Go语言 1.12 版本之前,要启用 go module 工具首先要设置环境变量 GO111MODULE,不过在Go语言 1.13 及以后的版本则不再需要设置环境变量。通过 GO111MODULE 可以开启或关闭 go module 工具。

Go.mod其实就是一个Modules,关于Modules的官方定义为:

Modules是相关Go包的集合,是源代码交换和版本控制的单元。go命令直接支持使用Modules,包括记录和解析对其他模块的依赖性。Modules替换旧的基于GOPATH的方法,来指定使用哪些源文件。

Modules和传统的GOPATH不同,不需要包含例如src,bin这样的子目录,一个源代码目录甚至是空目录都可以作为Modules,只要其中包含有go.mod文件。

go mod的优势

  • 项目不在需要放到$GOPATH/src
  • 依赖包的版本控制
    依赖包的版本交由go.mod文件控制。在go.mod用require语句指定包和版本 ,go命令会根据指定的路径和版本下载包,指定版本时可以用latest,这样它会自动下载指定包的最新版本;如果,go.mod中没有指定,go命令会自动下载代码中的依赖的最新版本。
module test

go 1.16

require (
	github.com/satori/go.uuid v1.2.0
	google.golang.org/appengine v1.6.1 // indirect
)
  • 依赖包中的地址失效的解决方案
    在go快速发展的过程中,由于一些依赖包地址变更而导致无法下载问题。以前的做法:
    1.修改源码,用新路径替换import的地址
    2.git clone 或 go get 新包后,copy到$GOPATH/src里旧的路径下
    但无论什么方法,都不便于维护,特别是多人协同开发时。
    而在gomod模式下,只需要在go.mod文件里用 replace 替换包,例如
    replace golang.org/x/text => github.com/golang/text latest
    go会用 github.com/golang/text 替代golang.org/x/text,原理就是下载github.com/golang/text 的最新版本到 $GOPATH/pkg/mod/golang.org/x/text下。

  • 在项目中执行go get命令可以下载依赖包,并且还可以指定下载的版本

    1.运行go get -u将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
    2.运行go get -u=patch将会升级到最新的修订版本
    3.运行go get package@version将会升级到指定的版本号version

go mod的使用

1.首先,go的版本必须升级到1.11以上
2.设置GO111MODULE的值:

  • GO111MODULE 有三个值:off, on和auto(默认值)。
  • GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
  • GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。
  • GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
    ①当前目录在GOPATH/src之外且该目录包含go.mod文件
    ②当前文件在包含go.mod文件的目录下面。

go.mod 文件内提供了module, require、replace和exclude四个关键字。

module语句指定包的名字(路径)
require语句指定的依赖项模块
replace语句可以替换依赖项模块
exclude语句可以忽略依赖项模块

在使用go mod init 模块名称 命令后,会在当前目录下生成一个go.mod文件,之后的包的管理都是通过这个文件管理。
go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。
会除了go.mod之外,go命令还维护一个名为go.sum的文件,其中包含特定模块版本内容的预期加密哈希 ,go命令使用go.sum文件确保这些模块的未来下载检索与第一次下载相同的位,以确保项目所依赖的模块不会出现意外更改,无论是出于恶意、意外还是其他原因。

使用go mod的包管理方式,依赖的第三方包被下载到了$GOPATH/pkg/mod路径下。
常用命令

go mod download //下载依赖包
go mode edit        edit go.mod from tools or scripts 编辑go.mod
go mod graph //打印模块依赖图
go mod init        initialize new module in current directory 在当前目录初始化mod
go mod tidy //拉取缺少的模块,移除不用的模块。
go mod vendor //将依赖复制到vendor下
go mod verify      verify dependencies have expected content 验证依赖是否正确
go mod why //解释为什么需要依赖

老项目迁移到用gomod的包管理

从很多第三方的包管理工具迁移到 gomod 特别简单,直接运行 go mod init 即可。
如果没有使用任何第三方包管理工具,除了运行 go mod init 初始化以外,还要使用 go get ./… 或者使用go mod tidy下载安装所有依赖包,并更新 go.mod 和 go.sum 文件。
默认情况下,go get 命令使用 @latest 版本控制符对所有依赖进行下载,如果想要更改某一个包的版本,可以使用 go mod edit --require=…/…@v版本号 命令
若已有go.mod文件中的require中已有相关依赖,则直接运行go build 或go run即可自动下载依赖包。

示例讲解

前期准备

设置GO111MODULE的值

go env -w GO111MODULE=on

在opt目录下创建项目

image-20220807180425684

这次不用创建src目录,也不用专门去设置GOPATH目录,我们可以把GOPATH目录设置在home目录下

go env -w GOPATH="/home"

生成go.mod文件

go mod init getUUID

image-20220807181347160

项目构建

同GOPATH构建项目一样,我们可以使用go build或者go install直接构建项目成一个二进制文件,如果不想生成二进制文件,则使用go run hhd.go直接运行代码。

使用go build

使用go module进行项目构建,我们只能去到getUUID项目根路径下执行构建命令

go build

image-20220807181428155

如果构建环境没有源代码所需要的第三方包,则需要进行go get下载或者使用go mod tidy

go mod tidy

该命令会自动下载项目所需要的第三方包,移除不使用的包

image-20220807181620790

执行完毕后,会把包安装在&GOPATH/pkg/mod目录下

image-20220807181752401

下载完第三方库后,我们在重新构建,构建成功后,便在当前目录生成可执行的二进制文件。

go build后面还可以携带源代码文件名进行构建,则生成的二进制文件名称是当前源代码文件名

go build hhd.go

image-20220807172707930

我们也可以指定生成的二进制名称

go build -o getID hhd.go

image-20220807172828331

使用go install

跟go build一样,使用go module进行项目构建,我们只能去到getUUID项目根路径下执行构建命令,执行以下命令进行构建代码

go install

构建成功后,会在GOPATH路径下会自动生成bin目录,然后把生成的二进制文件存放在bin目录中

image-20220807182410521

当然,go install 后面可以携带源代码文件名进行构建,同样也得去getUUID目录下执行构建命令。不过要注意,go install命令不能指定生成的二进制可执行文件的名称

go install hhd.go

image-20220807182657034

posted on 2022-08-07 18:28  xufat  阅读(988)  评论(0)    收藏  举报

导航

/* 返回顶部代码 */ TOP