Go lang使用包(package)这种概念元素来统筹代码,所有代码功能上的可调用性都定义在包这个级别,如果我们需要调用依赖,那就“导包”就行了,无论是内部的还是外部的,使用import关键字即可。但事情往往没有那么简单,Go lang在包管理机制上走了不少弯路,虽然1.18版本的包管理已经趋于成熟,但前事不忘后事之师,我们还是需要了解一下这段历史。

环境变量

一般情况下,go lang在系统中会依赖两个环境变量,分别是:GOPATH 和 GOROOT,有点类似于Python的解释器目录的概念,GOROOT 这个变量的作用就是为了告诉当前运行的 Go 进程当前 Go安装路径,当要运行的时候去什么位置找GoSDK相关的类。

GOPATH 这个变量的设定是默认所有的项目和引用的第三方包都下载到GOPATH的src目录下,也就是说,你的代码只要不在GOPATH里,就没法编译。我们可以理解这个目录就是项目目录,这一点跟Python区别还是挺大的,Python的pip包管理机制至今都是经典的包依赖设计模式。

GOPATH这种设定方式会导致很多问题,比方说我有很多go lang项目,而每个项目又都有自己的GOPATH目录,那所有依赖的包就都在项目各自目录下,导致重复包过多,反之,如果大家都用一个GOPATH目录,又会带来版本问题,每个项目依赖的包版本不一致,到底怎么进行统筹又是一个问题,这就是GOPATH设定早期被人诟病的原因。

Go modules

针对因为GOPATH这种反人类的设计而导致的包管理乱象,Go lang 1.11 版本的时候推出了新特性 Go modules。

Go modules 是官方推出的依赖管理工具,Go modules 提供了3个重要的功能:

1.go.mod 文件,它和Node的package.json文件的功能相似,都是记录当前项目的依赖关系。

2.机器生成的传递依赖项描述文件 : go.sum。

3.不再有 GOPATH 的反人类限制,所有代码可以位于电脑的任何路径中。

go lang1.18早已经集成了Go modules,但就像golang1.18第一篇精炼教程里写得那样,默认还是反人类的GOPATH模式,你想用,得通过命令手动开启:

  1. go env -w GO111MODULE=on

为了能够向下兼容维护go1.11版本以下的项目,可以设置为兼容模式:

  1. go env -w GO111MODULE=auto

三方包管理

三方包指的是外部开源的一些包,而使用go modules机制管理三方包相对简单,首先新建一个项目目录,比如c:/www/test

  1. cd c:/www/test

进入项目目录后,初始化项目:

  1. go mod init test

系统返回:

  1. C:\Users\liuyue\www\test>go mod init test
  2. go: creating new go.mod: module test
  3. C:\Users\liuyue\www\test>dir
  4. 2022/08/12 12:13 <DIR> .
  5. 2022/08/12 12:13 <DIR> ..
  6. 2022/08/12 12:13 21 go.mod
  7. 1 个文件 21 字节
  8. 2 个目录 228,767,113,216 可用字节

这里注意项目名和目录名称要吻合,go.mod 文件是开启 modules 的必备配置文件。它记录了当前项目引用的包数据信息。go.mod 文件中定义了以下关键词:

module:用于定义当前项目的模块路径

go:用于设置Go 版本信息

require:用于设置一个特定的模块版本

exclude:用于从使用中排除一个特定的模块版本

replace:用于将一个模块版本替换为另一个模块版本

接着,运行go get命令安装三方包,比如说gin框架:

  1. go get github.com/gin-gonic/gin

随后编写main.go文件,也就是main包:

  1. package main
  2. import (
  3. "github.com/gin-gonic/gin"
  4. )
  5. func main() {
  6. d := gin.Default()
  7. d.GET("/", func(c *gin.Context) {
  8. c.JSON(200, gin.H{"message": "hello go 1.18", "data": ""})
  9. })
  10. d.Run("127.0.0.1:5000")
  11. }

这里将刚刚安装的三方包导入,然后再main函数中调用。

紧接着启动服务:

  1. go run main.go

系统返回:

  1. C:\Users\liuyue\www\test>go run main.go
  2. [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
  3. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
  4. - using env: export GIN_MODE=release
  5. - using code: gin.SetMode(gin.ReleaseMode)
  6. [GIN-debug] GET / --> main.main.func1 (3 handlers)
  7. [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
  8. Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
  9. [GIN-debug] Listening and serving HTTP on 127.0.0.1:5000
  10. [GIN] 2022/08/12 - 12:19:20 |[97;42m 200 [0m| 3.8876ms | 127.0.0.1 |[97;44m GET [0m "/"
  11. [GIN] 2022/08/12 - 12:19:21 |[90;43m 404 [0m| 0s | 127.0.0.1 |[97;44m GET [0m "/favicon.ico"

说明三方包的服务已经启动了,访问http://localhost:5000:

这就是一个go lang项目导入三方包的具体流程。

接着我们打开项目中的go.mod文件:

  1. module test
  2. go 1.18
  3. require (
  4. github.com/gin-contrib/sse v0.1.0 // indirect
  5. github.com/gin-gonic/gin v1.8.1 // indirect
  6. github.com/go-playground/locales v0.14.0 // indirect
  7. github.com/go-playground/universal-translator v0.18.0 // indirect
  8. github.com/go-playground/validator/v10 v10.10.0 // indirect
  9. github.com/goccy/go-json v0.9.7 // indirect
  10. github.com/json-iterator/go v1.1.12 // indirect
  11. github.com/leodido/go-urn v1.2.1 // indirect
  12. github.com/mattn/go-isatty v0.0.14 // indirect
  13. github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
  14. github.com/modern-go/reflect2 v1.0.2 // indirect
  15. github.com/pelletier/go-toml/v2 v2.0.1 // indirect
  16. github.com/ugorji/go/codec v1.2.7 // indirect
  17. golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
  18. golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
  19. golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
  20. golang.org/x/text v0.3.6 // indirect
  21. google.golang.org/protobuf v1.28.0 // indirect
  22. gopkg.in/yaml.v2 v2.4.0 // indirect
  23. )

三方包gin以及gin所依赖的三方包都一目了然。

内部包管理

内部包指的是项目内部的包,一般情况下就是自己开发的可复用的包,go modules也可以对内部包进行管理,在刚刚创建的test项目中,新建目录my:

  1. C:\Users\liuyue\www\test>mkdir my
  2. C:\Users\liuyue\www\test>dir
  3. 驱动器 C 中的卷没有标签。
  4. 卷的序列号是 0A64-32BF
  5. C:\Users\liuyue\www\test 的目录
  6. 2022/08/12 12:39 <DIR> .
  7. 2022/08/12 12:13 <DIR> ..
  8. 2022/08/12 12:18 1,046 go.mod
  9. 2022/08/12 12:18 6,962 go.sum
  10. 2022/08/12 12:16 228 main.go
  11. 2022/08/12 12:39 <DIR> my
  12. 3 个文件 8,236 字节
  13. 3 个目录 228,568,178,688 可用字节
  14. C:\Users\liuyue\www\test>

然后再my目录新建一个my.go文件:

  1. package my
  2. import "fmt"
  3. func New() {
  4. fmt.Println("我是my包")
  5. }

这里我们声明包与目录名一致,随后再声明一个New函数。

接着改写main.go内容:

  1. package main
  2. import (
  3. "fmt"
  4. "test/my"
  5. )
  6. func main() {
  7. fmt.Println("main run")
  8. // 使用my
  9. my.New()
  10. }

程序返回:

  1. main run
  2. 我是my

触类旁通,如果包不在同一个项目下:

  1. ├── moduledemo
  2. ├── go.mod
  3. └── main.go
  4. └── mypackage
  5. ├── go.mod
  6. └── mypackage.go

这个时候,mypackage也需要进行module初始化,即拥有一个属于自己的go.mod文件,内容如下:

  1. module mypackage
  2. go 1.18

然后我们在moduledemo/main.go中按如下方式导入:

  1. import (
  2. "fmt"
  3. "mypackage"
  4. )
  5. func main() {
  6. mypackage.New()
  7. fmt.Println("main")
  8. }

结语

对于 Go lang 的项目来说,如果没有开启 go mod模式,那么项目就必须放在 GOPATH/src 目录下,项目本身也可以看作为一个本地包,可以被其它 GOPATH/src目录下的项目引用,同时也可以被go modules模式的项目引入,因为go modules的原理是先去GOPATH/src目录下寻址,如果没有才去指定目录寻址,但反过来,如果是放在go modules项目中的本地包,GOPATH/src目录下的项目就无法引用,因为GOPATH规定项目都必须得放在GOPATH/src目录下,它只会在GOPATH/src目录下寻址,这是我们需要注意的地方。

层次分明井然有条,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang包管理机制(package)EP10的更多相关文章

  1. 仙人指路,引而不发,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中New和Make函数的使用背景和区别EP16

    Golang只有二十五个系统保留关键字,二十几个系统内置函数,加起来只有五十个左右需要记住的关键字,纵观编程宇宙,无人能出其右.其中还有一些保留关键字属于"锦上添花",什么叫锦上添 ...

  2. 延宕执行,妙用无穷,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中defer关键字延迟调用机制使用EP17

    先行定义,延后执行.不得不佩服Go lang设计者天才的设计,事实上,defer关键字就相当于Python中的try{ ...}except{ ...}finally{...}结构设计中的finall ...

  3. 清源正本,鉴往知来,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中引用类型是否进行引用传递EP18

    开篇明义,Go lang中从来就不存在所谓的"引用传递",从来就只有一种变量传递方式,那就是值传递.因为引用传递的前提是存在"引用变量",但是Go lang中从 ...

  4. 你有对象类,我有结构体,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang结构体(struct)的使用EP06

    再续前文,在面向对象层面,Python做到了超神:万物皆为对象,而Ruby,则干脆就是神:飞花摘叶皆可对象.二者都提供对象类操作以及继承的方式为面向对象张目,但Go lang显然有一些特立独行,因为它 ...

  5. 百亿数据百亿花, 库若恒河沙复沙,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang数据库操作实践EP12

    Golang可以通过Gorm包来操作数据库,所谓ORM,即Object Relational Mapping(数据关系映射),说白了就是通过模式化的语法来操作数据库的行对象或者表对象,对比相对灵活繁复 ...

  6. 兔起鹘落全端涵盖,Go lang1.18入门精炼教程,由白丁入鸿儒,全平台(Sublime 4)Go lang开发环境搭建EP00

    Go lang,为并发而生的静态语言,源于C语言又不拘泥于性能,高效却不流于古板,Python灵活,略输性能,Java严谨,稍逊风骚.君不见各大厂牌均纷纷使用Go lang对自己的高并发业务进行重构, ...

  7. 化整为零优化重用,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang函数的定义和使用EP07

    函数是基于功能或者逻辑进行聚合的可复用的代码块.将一些复杂的.冗长的代码抽离封装成多个代码片段,即函数,有助于提高代码逻辑的可读性和可维护性.不同于Python,由于 Go lang是编译型语言,编译 ...

  8. 因势而变,因时而动,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang泛型(generic)的使用EP15

    事实上,泛型才是Go lang1.18最具特色的所在,但为什么我们一定要拖到后面才去探讨泛型?类比的话,我们可以想象一下给小学一年级的学生讲王勃的千古名篇<滕王阁序>,小学生有多大的概率可 ...

  9. 巨细靡遗流程控制,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang流程结构详解EP09

    流程结构就是指程序逻辑到底怎么执行,进而言之,程序执行逻辑的顺序.众所周知,程序整体都是自上由下执行的,但有的时候,又不仅仅是从上往下执行那么简单,大体上,Go lang程序的流程控制结构一共有三种: ...

随机推荐

  1. 羽夏笔记—— AT&T 与 GCC

    写在前面   本文是本人根据<AT&T 汇编语言与 GCC 内嵌汇编简介>进一步整理,修改了一些错误,并删除我并不能复现代码相关的部分.该文章一是我对 AT&T 的学习记录 ...

  2. Druid数据库连接池使用体验

    写在前面 在实际工作中我们我们使用较多的则是Spring默认的HikariDataSource数据库连接池,但是它无法提供可视化监控SQL这一能力,而这在很多场景下往往又是我们需要的功能,因此今天来学 ...

  3. atcoder abc 244

    atcoder abc 244 D - swap hats 给定两个 R,G,B 的排列 进行刚好 \(10^{18}\) 次操作,每一次选择两个交换 问最后能否相同 刚好 \(10^{18}\) 次 ...

  4. 超级重磅!Apache Hudi多模索引对查询优化高达30倍

    与许多其他事务数据系统一样,索引一直是 Apache Hudi 不可或缺的一部分,并且与普通表格式抽象不同. 在这篇博客中,我们讨论了我们如何重新构想索引并在 Apache Hudi 0.11.0 版 ...

  5. 七、服务器硬件及RAID配置实战

    一.RAID磁盘阵列介绍 磁盘阵列的全名(Redundant Arrays of Inexpensive Disk,RAID),中文简称是独立冗余磁盘阵列.冗余(如果磁盘出现故障,可以保证数据不丢) ...

  6. 关键字——this,super,static,final

    this 理解为当前对象. //测试 public static void main(String[] args){ Person person = new Person(3, "xiaoM ...

  7. SAP APO-部署选项

    SAP SCM Server安装提供SAP APO功能模块的所有功能. 在SAP APO的附加部署模型中,以下组件可用作SAP APO工具的一部分- OTE-在附加部署模型中,无法通过SAP SCM服 ...

  8. Leetcode--Last Stone Weight II

    Last Stone Weight II 欢迎关注H寻梦人公众号 You are given an array of integers stones where stones[i] is the we ...

  9. sql-DQL-单表查询

    单表查询 select [distint]* 字段列表 from 表名列表 where 条件列表 group by 分组字段 having 分组之后的条件 order by 排序 limit 分页限定 ...

  10. window下Redis快速启动,以及闪退问题解决

    我下载的是免安装版的window版redis,解压后如下: 第一步:在解压的redis文件夹下新建一个redis-start.bat(window启动一般都是xx.bat) 第二步:打开redis.w ...