后浪笔记一零二四

go-get

1. 使用国内代理

从代理服务器中获取包(see ‘go help goproxy’): 在Go 1.13中,我们可以通过GOPROXY来设置代理,通过GOPRIVATE控制私有库不走代理。

1
2
3
4
5
6
7
8
9
export GO111MODULE=on # ⽤于开启Go Module功能,解决依赖包依赖问题
export GOPROXY="https://goproxy.cn,direct"   #[设置外网代理]
export GOSUMDB=sum.golang.google.cn
export PATH=${GOPATH}/bin:$PATH
# 设置代理
export http_proxy=http://127.0.0.1:12639   # [设置内网代理]
export https_proxy=http://127.0.0.1:12639
export no_proxy=127.0.0.1 # 最好加上你本机的IP地址,否则本地微服务调试可能会出现问题
export GIT_TERMINAL_PROMPT=1 # 下载私有仓库依赖库时,可能会需要该环境变量

2. go包管理的两种模式

① GOPATH mode(vendor mode) 会现在当前目录或者当前目录的父级目录下的vendor目录中寻找依赖,如果没有找到,就在$GOPATH/src下寻找依赖

因为在vendor模式中,优先从verdor目录中查询依赖,如果A和B同时在vendor中依赖了某个github包,在A调用B中某个需要使用github包作为参数的方法的时候, 会报类型不一致异常。 要解决这个问题,必须把B的vendor目录删掉,并把B项目copy到A项目的vendor目录下,以保证A,和B引用的是同一份github代码。

② module-aware mode 忽略vendor目录,直接在$GOPATH/pkg/mod目录下寻找依赖

3. go list命令

go list -m # print path of main module go list -m -f={{.Dir}} # print root directory of main module go list -m all # print build list

4. go get在下载包的时候如何指定版本:

go get github.com/gorilla/mux@latest # same (@latest is default for ‘go get’) go get github.com/gorilla/mux@v1.6.2 # records v1.6.2 go get github.com/gorilla/mux@e3702bed2 # records v1.6.2 (e3702bed2这个提交新建了v1.6.2tag) go get github.com/gorilla/mux@c856192 # records v0.0.0-20180517173623-c85619274f5d (伪版本:表示master分支的最后一次提交) go get github.com/gorilla/mux@master # records current meaning of master (伪版本:表示master分支的最后一次提交)

5. go get命令使用github的私有仓库

  1. 登录 Github 账号,然后到 Setting -> Personal access tokens
  2. 创建一个有访问私有仓库权限的 token
  3. 然后执行
1
2
export GITHUB_TOKEN=xxx
git config --global url."https://${GITHUB_TOKEN}:x-oauth-basic@github.com/kounta".insteadOf "https://github.com/kounta"

6. 伪版本

Pseudo-versions

The go.mod file and the go command more generally use semantic versions as the standard form for describing module versions, so that versions can be compared to determine which should be considered earlier or later than another. A module version like v1.2.3 is introduced by tagging a revision in the underlying source repository. Untagged revisions can be referred to using a “pseudo-version” like v0.0.0-yyyymmddhhmmss-abcdefabcdef, where the time is the commit time in UTC and the final suffix is the prefix of the commit hash. The time portion ensures that two pseudo-versions can be compared to determine which happened later, the commit hash identifes the underlying commit, and the prefix (v0.0.0- in this example) is derived from the most recent tagged version in the commit graph before this commit.

There are three pseudo-version forms:

vX.0.0-yyyymmddhhmmss-abcdefabcdef is used when there is no earlier versioned commit with an appropriate major version before the target commit. (This was originally the only form, so some older go.mod files use this form even for commits that do follow tags.)

vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef is used when the most recent versioned commit before the target commit is vX.Y.Z-pre.

vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the most recent versioned commit before the target commit is vX.Y.Z.

Pseudo-versions never need to be typed by hand: the go command will accept the plain commit hash and translate it into a pseudo-version (or a tagged version if available) automatically. This conversion is an example of a module query.

7. MVS算法的目标是选择满足所有依赖关系的最低版本,以减少引入不必要的新功能和潜在的兼容性问题

在GO项目中,如果两个依赖包都依赖于同一个库的不同版本,Go Module会使用一种称为“最小版本选择”(Mininal Version Selection,MVS)的算法来解决这种依赖冲突。具体来说,MVS算法会尝试选择一个能满足所有依赖关系的最低版本。

依赖冲突解决步骤:

  1. 识别依赖关系:
  • go会解析go.mod文件中的所有依赖关系,包括直接依赖和间接依赖。
  • 例如,假如,你的项目依赖于A v1.0.0和B v1.0.0,而A依赖于C v1.0.0,B依赖于C v2.0.0
  1. 选择最高版本
  • 如果C v2.0.0向后兼容C v1.0.0,Go会选择C v2.0.0,因为这个版本可以同时满足A和B的需求。
  • 如果C v2.0.0不向后兼容C v1.0.0,Go会尝试找到一个中间版本,或者选择C v2.0.0并希望A可以正常工作
  1. 生成 go.mod 文件
  • Go会在go.mod文件中记录最终选择的依赖版本。
  1. 验证依赖
  • Go会验证选择的版本是否满足所有依赖关系,并生成go.sum文件来记录每个依赖包的校验和,确保依赖包的一致性和完整性。

包的基本概念

  • 基本概念:
    • Go语言的包借助了目录树的组织形式,一般包的名称就是其源文件所在目录的名称
    • 包的习惯用法:
      • 包名一般是小写的,使用一个简短的命名
      • 包名一般要和所在的目录同名
      • 包一般放到公司的域名目录下,这样能保证包名的唯一性,便于共享代码。
        • 比如,个人的github项目的包一般放到$GOPATH/src/github.com/username/projectname目录下。
  • 包引用
    • 包引用路径
      • 全路径引用:包的绝对路径就是“$GOROOT/src或$GOPATH/src”后面包的源码的全路径
      • 相对路径引用:
        • 相对路径只能引用$GOPATH下的包,标准包的引用只能使用全路径引用。
    • 包引用格式
      • 标准引用:import "fmt"
      • 别名引用:import F "fmt"
      • 省略引用:import . "fmt"
      • 仅执行包初始化init函数:import _ "fmt"
    • 注意:
      • 一个包可以有多个init函数,包加载会执行全部的init函数,但并不能保证执行顺序
      • 包不能出现环形引用。比如包a引用了包b,包b引用了包c,如果包c又引用了包a,则编译不能通过
      • 包的重复引用是允许的。比如包a引用了包b和包c,包b和包c都引用了包d。这种情况相当于重复引用了d,这种情况是允许的,并且Go编译器保证d的init函数只会执行一次。
  • 包加载
    • 包初始化程序从main函数引用的包开始,逐级查找包的引用,直到找到没有引用其他包的包,最终生成一个包引用的有向无环图。
    • Go编译器会将有向无环图转换为一棵树,然后从树的叶子节点开始逐层向上对包进行初始化。
    • 单个包在初始化时,先初始化常量,然后是全局变量,最后执行包的init函数(如果有)。

专题:

本文发表于 2022-09-13,最后修改于 2022-09-13。

本站永久域名「 jiavvc.top 」,也可搜索「 后浪笔记一零二四 」找到我。


上一篇 « go-test 下一篇 » go-build

赞赏支持

请我吃鸡腿 =^_^=

i ysf

云闪付

i wechat

微信

推荐阅读

Big Image