• go module模块使用相关


    Golang具有相当长的包管理工具的变迁史,由于官方没有实现足够好用的包管理工具,各种包管理工具层出不穷。

    GOPATH

    • 使用GOPATH管理依赖

    Golang的包管理方式最初采用的是monorepo模式,即所有包都放在GOPATH下,使用类似命名空间的包路径来区分包。

    几乎所有的包管理工具在Golang1.11版本之前都绕不开GOPATH环境变量,GOPATH主要用来放置项目依赖包的源代码。由于GOPATH不区分项目,代码中任何import的路径都需要从GOPATH为根目录的位置开始查找。

    $ go env | grep GOPATH
    set GOPATH=F:\Go\workspce
    

    GOPATH目录下包含三个子目录分别是bin、pkg、src

    子目录描述
    bin 存储编译后生成的二进制文件
    pkg 存储预编译的目标文件,以加快程序后续编译速度。
    src 存储源代码

    使用GOPATH方式管理项目依赖时,编写Go应用程序时,程序包和库文件会以$GOPATH/src/github.com/foo/bar的路径形式进行存放。因此就必须将项目源代码固定存放在$GOPATH/src目录下,若执行go get拉取外部依赖时会自动下载并安装到GOPATH目录下。

    使用GOPATH环境变量管理项目依赖包的缺点

    • 由于依赖包可能会引入破坏性的更新,会产生生产环境和测试环境不一致的问题。
    • 不区分依赖项的版本
      个项目时不同项目对于依赖库的版本需求经常是不一致的,然后却无法在一个GOPATH路径下放置不同版本的依赖项。因此只能通过人工判断更新,使用非常不便。
    • 依赖项列表无法数据化
      Go Modules之前是没有任何语义化的数据可以知道当前项目的所有依赖项,因此需要手工找出所有依赖。对项目而言,需要将所有依赖项全部放入到源代码控制中。若剔除某个依赖则需在源码中手工确认某个依赖是否被剔除。

    为解决GOPATH的缺陷,Go官方和社区推出了许多解决方案,比如godep、govendor、glide等。但这些工具要么无法彻底解决GOPATH存在的问题,要么使用起来繁冗。

    Go Modules

    • Go Modules是语义化版本管理依赖项的包管理工具,解决GOPATH存在的缺陷。
    • Go Modules的前身是vgo,于Golang v1.11新增特性。

    使用Go Modules后无需再将代码放置到GOPATH下的src目录中,Go Modules替换旧的基于GOPATH来指定在给定构件中使用的源文件。Go Modules可将项目文件夹下所有依赖整理后写入名为go.mod的项目依赖管理文件中。

    使用Go Modules管理项目依赖包时会在项目根目录下生成两个文件,分别是go.modgo.sum

    • go.mod文件中会记录当前项目的所有依赖项
    • go.sum文件中会记录每个依赖包的版本和对应哈希值

    go env

    查看当前Go版本

    $ go version
    go version go1.15.6 windows/amd64
    

    查看环境变量中Go模块的配置项,查看是否已开启Go Modules功能。

    配置项默认值描述
    GO111Modules off 是否开启Go Modules功能
    GOPROXY https://proxy.golang.org,direct 设置Golang代理商为用户提供包下载的地址
    $ go env
    set GO111MODULE=on
    set GOPROXY=https://goproxy.io
    

    GO111MODULE

    • GO111MODULE这个命名代表着Golang于1.11版本时添加对Go Modules的支持。
    • GO111MODULE具有三个可选值onoffauto(默认)
    描述
    auto 默认值,根据当前目录来决定是否启用Go Modules功能。
    off 禁用Go Modules功能
    on 启用Go Modules功能
    • auto默认值,go命令根据当前目录来决定是否启用Go Modules功能。
      只有在当前目录位于GOPATH/src之外且该目录包含go.mod文件,或者当前文件在包含go.mod文件的目录下时才会自动开启。
    • off表示go命令禁用Go Modules功能,寻找依赖包时将会沿用旧版本通过vendor目录或GOPATH模式来查找。
    • on表示go命令启用Go Modules功能,因此不会去GOPATH目录下查找依赖。

    命令行开启Go Modules功能

    $ export GO111MODULE = on
    

    当Go Modules模块功能开启后,依赖包的存放位置将会变更为$GOPATH/pkg,同时会允许同一个package包多个版本共存,且多个项目可以共享缓存的模块。

    GOPROXY

    • GOPROXY的值会以一个英文逗号,作为分隔符来分割多个Go依赖包代理商列表。
    • GOPROXY中的direct是一个特殊的标识符,用于指示Golang回溯到依赖项的源地址去抓取
    $ go env | grep GOPROXY
    set GOPROXY=https://goproxy.cn,direct
    

    中国Golang中间代理商包下载地址

    代理商地址
    Golang中国 https://goproxy.io
    阿里云 https://mirrors.aliyun.com/proxy/
    七牛云 https://goproxy.cn

    设置Golang代理商为七牛云

    $ go env -w GOPROXY=https://goproxy.cn,direct
    $ go env|grep GOPROXY
    set GOPROXY=https://goproxy.cn,direct


    (windows配置,控制面板环境变量
    选择“变量名”输入框并输入“GO111MODULE” 7. 选择“变量值”输入框并输入“on”
    8. 点击“确定”按钮 9. 点击“新建…”按钮
    10. 选择“变量名”输入框并输入“GOPROXY”
    11. 选择“变量值”输入框并输入“https://goproxy.cn”
    12. 点击“确定”按钮

    我们可以配置多个:
    https://goproxy.cn,https://goproxy.io,direct


    go env -w GO111MODULE=on
    go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct

    )

    go mod

    Go Modules包管理器提供了go mod命令用于管理项目依赖项。

    • go mod命令支持记录和解析对模块的依赖性
    • go mod管理项目依赖无需再将项目放到GOPATH/src指定目录下,可在磁盘的任何位置新建项目。
    $ go help mod 
    Usage:
    
            go mod <command> [arguments]
    
    The commands are:
    
            download    download modules to local cache
            edit        edit go.mod from tools or scripts
            graph       print module requirement graph
            init        initialize new module in current directory
            tidy        add missing and remove unused modules
            vendor      make vendored copy of dependencies
            verify      verify dependencies have expected content
            why         explain why packages or modules are needed
    
    Use "go help mod <command>" for more information about a command.
    
    命令描述
    go mod download 下载依赖包
    go mod edit 编辑go.mod文件
    go mod graph 打印模块依赖图
    go mod init 当前目录下初始化模块
    go mod tidy 拉取缺少的依赖项或移除无用的依赖项
    go mod vendor 将依赖复制到项目根目录下的vendor目录中
    go mod verify 验证依赖项的哈希值是否正确
    go mod why 解释为什么需要依赖

    go mod init

    初始化Go Modules,首先需要进入项目根目录,执行Go Modules初始化命令,生成go.mod项目依赖管理文件。

    $ mkdir projname && cd projname
    $ go mod init projname
    

    使用go mod init初始化项目依赖后会生成两个文件

    文件描述
    go.mod 项目依赖包管理文件
    go.sum 项目依赖包的版本控制文件

     




    Go get

    go get 命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装。整个过程就像安装一个 App 一样简单。

    go help get
    usage: go get [-d] [-t] [-u] [-v] [build flags] [packages]

    Get resolves its command-line arguments to packages at specific module versions,
    updates go.mod to require those versions, downloads source code into the
    module cache, then builds and installs the named packages.

    To add a dependency for a package or upgrade it to its latest version:

    go get example.com/pkg

    To upgrade or downgrade a package to a specific version:

    go get example.com/pkg@v1.2.3

    To remove a dependency on a module and downgrade modules that require it:

    go get example.com/mod@none

    See https://golang.org/ref/mod#go-get for details.

    The 'go install' command may be used to build and install packages. When a
    version is specified, 'go install' runs in module-aware mode and ignores
    the go.mod file in the current directory. For example:

    Go语言的代码被托管于 Github.com 网站,该网站是基于 Git 代码管理工具的,很多有名的项目都在该网站托管代码。其他类似的托管网站还有 code.google.com、bitbucket.org 等。

    go get "golang.org/x/tour/wc"
    go: downloading golang.org/x/tour v0.1.0
    go get: added golang.org/x/tour v0.1.0

    获取前,请确保 GOPATH 已经设置。Go 1.8 版本之后,GOPATH 默认在用户目录的 go 文件夹下。
    (看到下载到用户目录了:


    cellnet 只是一个网络库,并没有可执行文件,因此在 go get 操作成功后 GOPATH 下的 bin 目录下不会有任何编译好的二进制文件。

    需要测试获取并编译二进制的,可以尝试下面的这个命令。当获取完成后,就会自动在 GOPATH 的 bin 目录下生成编译好的二进制文件。

    $ go get github.com/davyxu/tabtoy

     

    go get 使用时的附加参数

    使用 go get 时可以配合附加参数显示更多的信息及实现特殊的下载和安装操作,详见下表所示。

    go get 使用时的附加参数
    附加参数备  注
    -v 显示操作流程的日志及信息,方便检查错误
    -u 下载丢失的包,但不会更新已经存在的包
    -d 只下载,不安装
    -insecure 允许使用不安全的 HTTP 方式进行下载操作

     我们可以使用这些附加参数。

     

     

    检测依赖

    go mod tidy

    tidy会检测该文件夹目录下所有引入的依赖,写入 go.mod 文件

    写入后你会发现 go.mod 文件有所变动

    下载依赖

    我们需要将依赖下载至本地,而不是使用 go get

    go mod download

    如果你没有设置 GOPROXY 为国内镜像,这步百分百会夯住到死

    此时会将依赖全部下载至 GOPATH 下,会在根目录下生成 go.sum 文件, 该文件是依赖的详细依赖, 但是我们开头说了,我们的项目是没有放到 GOPATH 下的,那么我们下载至 GOPATH 下是无用的,照样找不到这些包

    导入依赖

    go mod vendor

    执行此命令,会将刚才下载至 GOPATH 下的依赖转移至该项目根目录下的 vendor(自动新建) 文件夹下

     此时我们就可以使用这些依赖了

    GOLAND设置开启 GO MODULE

    可能是因为 GO MODULE 功能还需完善,GOLAND默认是关闭该功能的,我们需要手动打开(不排除之后更新会不会改成默认开启)

    依赖更新

    这里的更新不是指版本的更新,而是指引入新依赖

    依赖更新请从检测依赖部分一直执行即可,即

    go mod tidy
    go mod download
    go mod vendor

    新增依赖

    有同学会问,不使用 go get ,我怎么在项目中加新包呢?

    直接项目中 import 这个包,之后更新依赖即可

    在协作中使用 GOMODULE#

    要注意的是, 在项目管理中,如使用git,请将 vendor 文件夹放入白名单,不然项目中带上包体积会很大

    git设置白名单方式为在git托管的项目根目录新建 .gitignore 文件

     设置忽略即可.

    但是 go.mod 和 go.sum 不要忽略

    另一人clone项目后在本地进行依赖更新(同上方依赖更新)即可

    GOMODULE常用命令#

    复制代码
    go mod init  # 初始化go.mod
    go mod tidy  # 更新依赖文件
    go mod download  # 下载依赖文件
    go mod vendor  # 将依赖转移至本地的vendor文件
    go mod edit  # 手动修改依赖文件
    go mod graph  # 打印依赖图
    go mod verify  # 校验依赖
     

     

     

     参考:

    https://www.cnblogs.com/chnmig/p/11806609.html

     https://www.jianshu.com/p/277e4490e6ab

     

     

     go.mod文件

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

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

     

    go.mod文件中通过指令声明module信息,用于控制命令行工具进行版本选择。一共有四个指令可供使用:

    • module: 声明module名称;
    • require: 声明依赖以及其版本号;
    • replace: 替换require中声明的依赖,使用另外的依赖及其版本号;
    • exclude: 禁用指定的依赖;

     

    go module使用本地包的方法示例

    go module的使用非常简单

    初始化go.mod

    1
    go mod init

    整理依赖包

    1
    go mod tidy

    如果想缓存到vendor目录

    1
    go mod vendor

    执行命令之后都会自动把依赖搞定.

    但是, 如果我们是本地开发的包, 还没有远程仓库的时候, 要怎么解决本地包依赖问题呢?

    使用replace将远程包替换为本地包服务

    幸运的是, go module 提供了另外一个方案, replace, 这个replace怎么使用的呢?

    我们先看一下一个最基本的mod文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    module GoRoomDemo
    go 1.12
    require (
      github.com/gin-gonic/gin v1.3.0
      github.com/gohouse/goroom v0.0.0-20190327052827-9ab674039336
      github.com/golang/protobuf v1.3.1 // indirect
      github.com/gomodule/redigo v2.0.0+incompatible
      github.com/mattn/go-sqlite3 v1.10.0
      github.com/stretchr/testify v1.3.0 // indirect
      golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53 // indirect
    )

     这是一个简单的GoRoom框架的依赖关系包, 如果我想使用本地的goroom, 只需要使用replace即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    module GoRoomDemo
     
    go 1.12
     
    require (
      github.com/gin-gonic/gin v1.3.0
      github.com/gohouse/goroom v0.0.0-20190327052827-9ab674039336
      github.com/golang/protobuf v1.3.1 // indirect
      github.com/gomodule/redigo v2.0.0+incompatible
      github.com/mattn/go-sqlite3 v1.10.0
      github.com/stretchr/testify v1.3.0 // indirect
      golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53 // indirect
    )
     
    replace github.com/gohouse/goroom => /path/to/go/src/github.com/gohouse/goroom

    这里的 path/to/go/src/github.com/gohouse/goroom 是本地的包路径

    这样, 我们就可以愉快的使用本地目录了。

    gee/
    |--gee.go
    |--go.mod
    main.go
    go.mod



    main.go想使用gee的包,这么写外面的go.mod
    module example

    go 1.17

    require gee v0.0.0

    replace gee => ./gee
     
     
    require github.com/google/uuid  =>  本地的某个目录
     
     

    replace使用场景

    调试依赖包

    有时我们需要调试依赖包,此时就可以使用replace来修改依赖,如下所示:

    replace (
    github.com/google/uuid v1.1.1 => ../uuid
    golang.org/x/text v0.3.2 => github.com/golang/text v0.3.2
    )
    

    语句github.com/google/uuid v1.1.1 => ../uuid使用本地的uuid来替换依赖包,此是,我们可以任意的修改../uuid目录的内容来进行调试。

    除了使用相对路径,还可以使用绝对路径,甚至还可以使用自已的fork仓库。

    禁止被依赖

    另一种使用replace的场景是你的module不希望被直接引用,比如开源软件kubernetes,在它的go.modrequire部分有大量的v0.0.0依赖,比如:

    module k8s.io/kubernetes
    
    require (
    	...
    	k8s.io/api v0.0.0
    	k8s.io/apiextensions-apiserver v0.0.0
    	k8s.io/apimachinery v0.0.0
    	k8s.io/apiserver v0.0.0
    	k8s.io/cli-runtime v0.0.0
    	k8s.io/client-go v0.0.0
    	k8s.io/cloud-provider v0.0.0
    	...
    )
    

    由于上面的依赖都不存在v0.0.0版本,所以其他项目直接依赖k8s.io/kubernetes时会因无法找到版本而无法使用。 因为Kubernetes不希望做为module被直接使用,其他项目可以使用kubernetes其他子组件。

    kubernetes 对外隐藏了依赖版本号,其真实的依赖通过replace指定:

    replace (
    	k8s.io/api => ./staging/src/k8s.io/api
    	k8s.io/apiextensions-apiserver => ./staging/src/k8s.io/apiextensions-apiserver
    	k8s.io/apimachinery => ./staging/src/k8s.io/apimachinery
    	k8s.io/apiserver => ./staging/src/k8s.io/apiserver
    	k8s.io/cli-runtime => ./staging/src/k8s.io/cli-runtime
    	k8s.io/client-go => ./staging/src/k8s.io/client-go
    	k8s.io/cloud-provider => ./staging/src/k8s.io/cloud-provider
    )
    

    前面我们说过,replace指令在当前模块不是main module 时会被自动忽略的,Kubernetes正是利用了这一特性来实现对外隐藏依赖版本号来实现禁止直接引用的目的。

     使用go module

    1 先编辑go.mod

    2 go mod tidy # 检测依赖的包,下载使用到的包,剔除未使用的包  # 如果你希望将第三方依赖包放至在本项目下,可以使用该命令,此时会将第三方依赖下载至vendor 目录中 go mod vendor

     

     在使用 Go module 过程中,随着引入的依赖增多,也许你会发现go.mod文件中部分依赖包后面会出现一个 // indirect的标识。这个标识总是出现在 require 指令中,其中 // 与代码的行注释一样表示注释的开始,indirect 表示间接的依赖。

    间接依赖出现在 go.mod 文件的情况,可能符合下面所列场景的一种或多种:

    • 直接依赖未启用 Go module
    • 直接依赖go.mod 文件中缺失部分依赖

    https://blog.csdn.net/qq_36025814/article/details/108725453

    GO]解决golang.org/x/ 下包下载不下来的问题

     

    因为在项目中要使用到一个golang.org的包,但是因为墙的问题,官方方法已经无法使用,但是在github上存在一个镜像站可以使用,我们只需要将它克隆下来就可以正常使用了

    mkdir -p $GOPATH/src/github.com/golang/
    git clone https://github.com/golang/sys.git $GOPATH/src/github.com/golang/sys
    git clone https://github.com/golang/net.git $GOPATH/src/github.com/golang/net
    git clone https://github.com/golang/text.git $GOPATH/src/github.com/golang/text
    git clone https://github.com/golang/lint.git $GOPATH/src/github.com/golang/lint
    git clone https://github.com/golang/tools.git $GOPATH/src/github.com/golang/tools
    git clone https://github.com/golang/crypto.git $GOPATH/src/github.com/golang/crypto
    
    ln -s $GOPATH/src/github.com/golang/ $GOPATH/src/golang.org/x


    由于Google相关的包无法直接下载,可以使用如果方式下载下来,然后创建软连接或者修改文件夹名称来解决:
    第一步:

    1.  
      git clone https://github.com/golang/net.git $GOPATH/src/github.com/golang/net
    2.  
      git clone https://github.com/golang/sys.git $GOPATH/src/github.com/golang/sys
    3.  
      git clone https://github.com/golang/tools.git $GOPATH/src/github.com/golang/tools
    4.  
      git clone https://github.com/golang/lint.git $GOPATH/src/github.com/golang/lint
    5.  
      ...

    通过查看 https://github.com/golang 可以获取更多的信息
    第二步:
    将net、sys、tools三个文件夹放到 $GOPATH/src/golang.org/x 目录下。或者Linux下可以创建软连接:

    ln -s $GOPATH/src/github.com/golang $GOPATH/src/golang.org/x

    说明:上述通过环境变量指示的路径如果有问题,可以使用其他路径表式(如绝对路径

    好的办法:

    go get层面增加代理
    go 1.11版本新增了 GOPROXY 环境变量,go get会根据这个环境变量来决定去哪里取引入库的代码

    $ export GOPROXY=https://goproxy.io
    1
    其中,https://goproxy.io 是一个goproxy.io这个开源项目提供的公开代理服务。
    ————————————————
    版权声明:本文为CSDN博主「孙雪峰」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/snowin1994/article/details/88358836

  • 相关阅读:
    手把手玩转win8开发系列课程(5)
    一道百度之星编程大赛题的随笔联想·(2)
    手把手玩转win8开发系列课程(7)
    手把手玩转win8开发系列课程(10)
    一道百度之星编程大赛题的随笔联想·(1)
    手把手玩转win8开发系列课程(6)
    手把手玩转win8开发系列课程(9)
    手把手玩转win8开发系列课程(3)
    Innodb 表修复
    NoSQL之【Redis】学习(二):配置说明
  • 原文地址:https://www.cnblogs.com/youxin/p/15996765.html
Copyright © 2020-2023  润新知