Golang(八)go modules 学习

0. 前言

  • 最近加入鹅厂学习 k8s,组内使用 Go 1.11 以上的 go modules 管理依赖,因此整理了相关资料
  • 本文严重参考原文:初窥Go module

1. 传统 Golang 包依赖管理

  • Golang 设计深受 Google 主干开发模型影响:

    • 所有开发人员基于主干 trunk/mainline 开发:提交到 trunk 或从 trunk 获取最新的代码(同步到本地 workspace)
    • 版本发布时,建立 Release branch,release branch 实质上就是某一个时刻主干代码的快照
    • release branch 上 的 bug fix 和增强改进代码也通常是先在主干上提交(commit),然后再 cherry-pick 到 release branch 上

  • Golang 中的 go get 的设计深受 Google 内部单一代码仓库(single monorepo)和基于主干(trunk/mainline based)的开发模型的影响:只获取 trunk/mainline 最新版本
  • go get 获取的代码会放在 $GOPATH/src 下面,而 go build 会在 $GOROOT/src 和 $GOPATH/src 下面按照 import path 去搜索 package
  • 由于 go get 获取的都是各个 package repo 的 trunk/mainline 的代码,因此 Go 1.5 之前的 Go compiler 都是基于目标 Go 程序依赖包的 trunk/mainline 代码去编译的
  • 这样的机制带来的问题包括:
    • trunk/mainline 代码时刻变化,不同人不同时刻获取的代码可能不同(即不能实现 reproduceable build)
    • 依赖包的 trunk 演进可能会导致代码无法编译
  • 为了实现 reporduceable build,Go 1.5 引入了 govendor 机制
    • Golang 编译器会优先在 vendor 下搜索依赖的第三方包
    • 开发者将特定版本的依赖包存放在 vendor 下面并提交到代码库
    • 那么所有人理论上都会得到同样的编译结果,从而实现reporduceable build
  • 在Go 1.5 发布后的若干年,Gopher 们把注意力都集中在如何利用 vendor 解决包依赖问题
    • 从手工添加依赖到 vendor
    • 手工更新依赖,到一众包依赖管理工具的诞生:比如: govendor、glide 以及号称准官方工具的 dep
    • 努力地尝试着按照当今主流思路解决着诸如:“钻石型依赖”等难题
  • 正当 Gopher 认为 dep 将顺理成章地升级为 go toolchain 一部分的时候,vgo 横空出世
  • 在原 Go tools 上简单快速地实现 了Go 原生的包依赖管理方案 ,vgo 就是 go modules 的前身

2. go modules 简介

  • 通常我们会在一个仓库中创建一组 package,仓库的路径比如:github.com/bigwhite/gocmpp 会作为 go package 的导入路径(import path)
  • GOPATH 模式下,编译器会根据 package 路径在 $GOPATH/src 或者 vendor 下逐级目录匹配
  • Go 1.8 版本中,如果开发者没有显式设置 $GOPATH,Go 会赋予 GOPATH 一个默认值(在 linux 上为 $HOME/go)
  • Go 1.11 给这样的一组在同一仓库下面的 packages 赋予了一个新的抽象概念:module
  • 并启用一个新的文件 go.mod 记录 module 的元信息
  • 一个仓库对应一个 module 或者多个 module
  • 在 go modules 下,仓库顶层目录下会放置一个 go.mod 文件,每个 go.mod 文件定义了一个 module,而放置 go.mod 文件的目录被称为 module root 目录(通常对应一个仓库的 root 目录,但不是必须的)
  • module root 目录以及其子目录下的所有 packages 均归属于该 module,除了那些自身包含 go.mod 文件的子目录
  • 在 go modules 下,Golang 编译器将不再在 GOPATH 下面以及 vendor 下面搜索目标程序依赖的第三方 packages

3. 尝试使用 go modules

  • 设置环境变量 GO111MODULE:

    • GO111MODULE=off:无模块支持,go 会从 GOPATH 和 vendor 文件夹寻找包
    • GO111MODULE=on:模块支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖
    • GO111MODULE=auto:在 $GOPATH/src 外面且根目录有 go.mod 文件时,开启模块支持
  • 在使用模块的时候,GOPATH 是无意义的,不过还是会把下载的依赖储存在 $GOPATH/pkg/mod 中,也会把 go install 的结果放在 $GOPATH/bin
  • 在 ~/test 下创建 hello 目录,然后写入 hello.go(此时不在 $GOPATH 中)

// hello.go
package main

import "bitbucket.org/bigwhite/c"

func main() {
    c.CallC()
}

  • 在 ~/test/hello 下创建 go.mod:

// go.mod
module hello

  • 构建 hello.go:

$ go build hello.go
go: finding bitbucket.org/bigwhite/c v1.3.0
go: downloading bitbucket.org/bigwhite/c v1.3.0
go: extracting bitbucket.org/bigwhite/c v1.3.0
go: finding bitbucket.org/bigwhite/d v1.2.0
go: downloading bitbucket.org/bigwhite/d v1.2.0
go: extracting bitbucket.org/bigwhite/d v1.2.0

$ ./hello.exe
call C: v1.3.0
   --> call D:
        call D: v1.2.0
   --> call D end

  • 查看 go.mod:

$ cat go.mod
// go.mod
module hello

go 1.12

require bitbucket.org/bigwhite/c v1.3.0 // indirect

  • indirect 指不是由主 mod 直接引用的包,而是由其他 mod 间接引用的包
  • 如果之后新增了该 mod 的直接引用,会删除上面的间接引用
  • go compiler 将下载的依赖包缓存在 $GOPATH/pkg/mod 下面:

$ pwd
/e/Coding/Golang/go/pkg/mod/cache/download

$ ls
bitbucket.org/     github.com/   golang.org/         gopkg.in/  sigs.k8s.io/
cloud.google.com/  go.uber.org/  google.golang.org/  k8s.io/

  • 具体执行:

$ ./hello.exe
call C: v1.3.0
   --> call D:
        call D: v1.2.0
   --> call D end

4. 参考文献

原文地址:https://www.cnblogs.com/wangao1236/p/11002871.html

时间: 2024-10-18 18:20:07

Golang(八)go modules 学习的相关文章

八、Android学习第七天——XML文件解析方法(转)

(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 八.Android学习第七天——XML文件解析方法 XML文件:extensible markup language 定义:用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 解析XML的方式: SAX——Simple API for XML,既是一种接口,也是一个软件包采用的是事件驱动,也就是它解析

[Golang][Mac]Go 语言学习资料记录

背景:最近的项目开发语言是GOlang 因此需要做一些简单了解和学习记录 又可以学习一下Google的新语言了,想想有些小激动哦~ 官方网站(需FQ才能打开,比如用蓝灯)https://golang.org/ 1. 下载安装:https://golang.org/ 2. 安装完毕后在Mac打开终端,配置环境变量以及创建目录 1 GOPATH=$HOME 2 echo $GOPATH 3 export PATH=$PATH:$(go env GOPATH)/bin 4 mkdir $HOME/go

golang 关于 interface 的学习整理

Golang-interface(四 反射) go语言学习-reflect反射理解和简单使用 为什么在Go语言中要慎用interface{} golang将interface{}转换为struct go reflect struct 遍历,反射 Golang Reflect反射的使用详解1 Go 语言反射三定律 原文地址:https://www.cnblogs.com/xuange306/p/10674158.html

第八周Java学习总结

一.知识点摘要 1.泛型 泛型(Generic):就是指参数化类型,上面的List就是参数化类型,因此就是泛型,而String就是该List泛型的类型参数.泛型可以使集合可以记住元素类型,即取出元素的时候无需进行强制类型转化了,可以直接用原类型的引用接收:一旦指定了性参数那么集合中元素的类型就确定了,不能添加其他类型的元素,否则会直接编译保存,这就可以避免了"不小心放入其他类型元素"的可能:上述保证了如果在编译时没有发出警告,则在运行时就一定不会产生类型转化异常(ClassCastEx

【基础知识八】集成学习

难点:如何产生"好而不同"的个体学习器:"好而不同":"准确性"和"多样性" 一.个体与集成 构建并结合多个学习器来完成学习任务 集成:结果通过投票法voting产生,"少数服从多数" 获得整体性能提升要求个体学习器:好而不同 1)个体学习器有一定的"准确性" 2)学习器间具有差异 集成学习的错误率: 假设基学习器的误差相互独立,随着集成中个体分类器数目T的增大,集成的错误率将指数级下降

golang 类型断言的学习

在php中有一个 serialize() 函数 可以把数组序列化成字符串进行存储和传输 如果想反序列化这种字符串,在php中只需要一个简单的unserialize() 函数就可以完成了.但是在golang中可就没有这么容易了,非得费个九牛二虎之力,写上不少代码才行. 这时候只想感叹一下,php真的是世界上最好的语言啊! 我就在今天的开发中遇到了这么个问题,需要使用golang去解析php序列化的字符串,在github上找了个解析的包,但是发现解析之后的结果是个interface{}类型. 顿时我

第八周技术学习+《你是锦瑟我为流年 三毛的千山万水》简记

上周大部分都在复习,并没有太多时间看书.然而各种考试压力过来,使我依然看完了我的<你是锦瑟我为流年 三毛的千山万水>,这本书以白落梅的个人角度评点三毛的生活踪迹,她的语言带给人一种平缓心情的感受,看着减缓了我很多压力.这里的三毛并非童话故事的三毛,而是以三毛为笔名的陈懋平,她小时候与书为伴.因为学校的一些原因,生命开始与流浪纠缠.仿佛生来就是一个流浪者,所以当她踏上行程,感觉人生原来可以这么活.她再也做不了一个安静温婉的女子,对着一扇幽窗,拿一支素笔,写着单薄的心事.她需要在放逐中,感受生命的

信息安全系统设计基础第八周期中学习总结—20135227黄晓妍

第一部分:实用的一些命令 man –k man –k xxx 同命令apropos 将搜索whatis数据库,模糊查找关键字如果记不清楚工具或者函数的完整名字,可以考虑用-k参数,例如,查找和printf有关的帮助:man -k printf 结合管道使用: man –k xxx | grep xxx | grep 1 xxx代表要搜索的关键字,1这里是man手册的命令的区段,一共由8个. 数字"1":可执行命令或shell命令 数字"2":系统调用(functio

初级篇第八期:学习写一个Model

学习建议:自己动手,丰衣足食 学习周期:1周 学习目的:熟练使用Obejct-C中基于NSObject的Model类 学习答疑:欢迎来技术群里提问并做分享 学习工具:Xcode开发环境 学习内容:熟悉Model的作用以及基本用法 我们在开发中为什么要创建Model,主要因为我们在接收服务器给我们返回的数据时候,我们需要用来保存这些数据,那么我们就会创建一个所谓的Model,其实就是基于NSObject类,然后创建一些它的属性,来保存相应的值,也方便其他的类来调用,当然了,我们要考虑在这个Mode