【Go】Go语言学习笔记--Go依赖管理

简介: 为什么需要依赖管理早期,Go所依赖的三方库都在GOPATH这个目录下面,这就导致同一个三方库职能保存一个版本,如果不同项目依赖不同版本的三方库,怎么解决?

依赖管理

为什么需要依赖管理

早期,Go所依赖的三方库都在GOPATH这个目录下面,这就导致同一个三方库职能保存一个版本,如果不同项目依赖不同版本的三方库,怎么解决?

godep

Go语言从v1.5开始引入vendor模式,如果项目目录下面有vendor目录,那么go工具链回优先使用vendor内的包进行编译、测试等,作用用途类似前端的npm包管理工具。

安装

执行下面的命令安装godep工具:

go get github.com/tools/godep
复制代码

基本命令

安装完毕以后,在终端输入godep查看支持的所有命令:

godep save  将依赖项输出并复制到Godeps.json文件中
godep go    使用保存的依赖项运行go工具
godep get   下载并安装具有指定依赖项的包
godep path  打印依赖的GOPATH路径
godep restore 在GOPATH中拉取依赖的版本
godep update 更新选定的包或go版本
godep diff 显示当前和以前保存的依赖项集之间的差异
godep version 查看版本信息
复制代码

使用godep

在项目目录下执行godep save命令,我这里遇到了一个错误:

godep: [WARNING]: godep should only be used inside a valid go package directory and
godep: [WARNING]: may not function correctly. You are probably outside of your $GOPATH.
godep: [WARNING]:       Current Directory: /Users/hometown/Desktop/golang-project/hello
godep: [WARNING]:       $GOPATH: /Users/hometown/stduy/go
godep: Unable to find SrcRoot for package .
复制代码

错误原因大致是说:

godep只能在有效的go软件包目录中使用
可能无法正常工作。你可能在$GOPATH之外
复制代码

所以我得出了一个结论:当用godep去管理项目依赖的时候,必须在GOPATH的src目录下的项目中执行。

回到指定目录重新执行,生成了一个Godepsvender两个文件夹。

Godeps文件夹下有一个Godeps.json的文件,记录项目依赖的包信息(类似package.josn)。

vender文件夹下是项目依赖的包的源代码文件(类似node_modules)。

vender机制

控制Go语言程序编译时依赖包搜索路径的优先级。

例如查找项目的某个依赖包,首先会在项目根目录下的vender文件夹下查找,如果没有找到就回去$GOPATH/src目录下查找,类似(去项目中的node_modules中找,如果没有找到,就去golbal node_modules中找)。

godep开发流程

  1. 保证程序能够正常编译
  2. 执行godep save保存当前项目的所有第三方依赖版本信息和代码
  3. 提交Godeps目录和vender目录到代码库
  4. 如果要更新依赖的版本,可直接修改Godeps.json文件中的对应项

go module

go module是Go1.11版本之后官方推出的版本管理工具,并且从GO1.13版本开始,go module将是Go语言默认的依赖管理工具。

GO111MODULE

要启用go module 需要设置环境变量GO111MODULE,有三个可选值offonauto,默认是auto

  1. off --> 禁用模块支持,编译时从GOPATH&vender文件夹中找包。
  2. on ---> 启用模块支持,编译时会忽略GOPATH&vender文件夹,只根据go.mod下载依赖。
  3. auto ---> 当项目在$GOPATH/src外且项目根目录有go.mod文件时,开启模块支持

简单来说,设置GO111MODULE=on之后就可以使用go module了,以后就没有必要在GOPATH中创建项目了,并且还能够很好的管理项目依赖的第三方包信息。

go mod 命令

go mod download 下载依赖的module到本地cache(默认为$GOPATH/pkg/mod 目录)
go mod edit 编辑go.mod文件
go mod graph 打印模块依赖图
go mod init 初始化当前文件夹,创建go.mod文件
go mod tidy 增加缺少的module,删除无用的module
go mod vendor 将依赖复制到vendor下
go mod verify 校验依赖
go mod why 解释为什么需要依赖
复制代码

go mod

module hello
go 1.17
require (
   github.com/kr/fs v0.1.0 // indirect
   github.com/kr/pretty v0.3.0 // indirect
   github.com/pmezard/go-difflib v1.0.0 // indirect
   github.com/tools/godep v0.0.0-20180126220526-ce0bfadeb516 // indirect
   golang.org/x/tools v0.1.9 // indirect
)
复制代码
  • module 是包名
  • require 用来定义依赖包及版本
  • indirect 表示间接引用

go get

go get下载依赖

  1. go get -u 升级到最新的次要版本或者修订版本
  2. go get -u=patch升级到最新的修订版本
  3. go get 包名@版本升级到指定版本号

go mod tidy

删除依赖代码后,相关依赖库不会自动从go.mod文件中删除,执行go mod tidy更新go.mod中的依赖关系(类似更新package.json执行npm uninstall xxx

项目中使用go module

现有项目

  1. 在项目目录下执行go mod init生成 go.mod 文件
  2. 执行go get,查找并记录当前项目的依赖,同时生成go.sum记录每个依赖库的版本和哈希值

新项目

  1. 执行go mod init 项目名
  2. 手动编辑go.mod或中的require依赖项或者go get自动发现。

使用go module导入本地包

导入本地包的时候碰到了一个问题,报错如下:

package xxx is not in GOROOT
复制代码

这是因为GOROOT下面没有这个包,Go引入包的方式两种GOPATH&go modgo mod引入包,开头以项目根目录执行go mod init 项目名的这个项目名开头(也是go.mod的module 名)。

解决了上面的问题以后就可以执行go run main.go执行成功了。

我这写了一个demo:

/main.go

package main
import (
    "fmt"
    "moduledemo/mypackage"
)
func main() {
    mypackage.DoSomething()
    fmt.Println("你好帅哥")
}
复制代码

/mypackage/mypackage.go

package mypackage
import "fmt"
func DoSomething() {
    fmt.Println("做点啥啊?Do something??")
}
复制代码

/hispackage/hispackage.go

package hispackage
import "fmt"
func DoSomething() {
    fmt.Println("他不做")
}
复制代码

执行成功!

遇到了一个新的问题,就是虽然可以执行成功,但是Goland标红,是因为编辑器没有配置(很无语),打开这个设置即可:

网络异常,图片无法展示
|


过程中还手动开启了GO111MODULE


目录
相关文章
|
10天前
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
41 0
|
1天前
|
数据采集 人工智能 搜索推荐
快速入门:利用Go语言下载Amazon商品信息的步骤详解
本文探讨了使用Go语言和代理IP技术构建高效Amazon商品信息爬虫的方法。Go语言因其简洁语法、快速编译、并发支持和丰富标准库成为理想的爬虫开发语言。文章介绍了电商网站的发展趋势,如个性化推荐、移动端优化和跨境电商。步骤包括设置代理IP、编写爬虫代码和实现多线程采集。提供的Go代码示例展示了如何配置代理、发送请求及使用goroutine进行多线程采集。注意需根据实际情况调整代理服务和商品URL。
快速入门:利用Go语言下载Amazon商品信息的步骤详解
|
3天前
|
存储 编译器 Go
Go语言学习12-数据的使用
【5月更文挑战第5天】本篇 Huazie 向大家介绍 Go 语言数据的使用,包含赋值语句、常量与变量、可比性与有序性
38 6
Go语言学习12-数据的使用
|
4天前
|
Java Go
一文带你速通go语言指针
Go语言指针入门指南:简述指针用于提升效率,通过地址操作变量。文章作者sharkChili是Java/CSDN专家,维护Java Guide项目。文中介绍指针声明、取值,展示如何通过指针修改变量值及在函数中的应用。通过实例解析如何使用指针优化函数,以实现对原变量的直接修改。作者还邀请读者加入交流群深入探讨,并鼓励关注其公众号“写代码的SharkChili”。
11 0
|
4天前
|
存储 缓存 Java
来聊聊go语言的hashMap
本文介绍了Go语言中的`map`与Java的不同设计思想。作者`sharkChili`是一名Java和Go开发者,同时也是CSDN博客专家及JavaGuide项目的维护者。文章探讨了Go语言`map`的数据结构,包括`count`、`buckets指针`和`bmap`,解释了键值对的存储方式,如何利用内存对齐优化空间使用,并展示了`map`的初始化、插入键值对以及查找数据的源码过程。此外,作者还分享了如何通过汇编查看`map`操作,并鼓励读者深入研究Go的哈希冲突解决和源码。最后,作者提供了一个交流群,供读者讨论相关话题。
15 0
|
5天前
|
Java Go
Go语言学习11-数据初始化
【5月更文挑战第3天】本篇带大家通过内建函数 new 和 make 了解Go语言的数据初始化过程
18 1
Go语言学习11-数据初始化
|
5天前
|
自然语言处理 安全 Java
速通Go语言编译过程
Go语言编译过程详解:从词法分析(生成token)到句法分析(构建语法树),再到语义分析(类型检查、推断、匹配及函数内联)、生成中间码(SSA)和汇编码。最后,通过链接生成可执行文件。作者sharkchili,CSDN Java博客专家,分享技术细节,邀请读者加入交流群。
23 2
|
6天前
|
Java Linux Go
一文带你速通Go语言基础语法
本文是关于Go语言的入门介绍,作者因其简洁高效的特性对Go语言情有独钟。文章首先概述了Go语言的优势,包括快速上手、并发编程简单、设计简洁且功能强大,以及丰富的标准库。接着,文章通过示例展示了如何编写和运行Go代码,包括声明包、导入包和输出语句。此外,还介绍了Go的语法基础,如变量类型(数字、字符串、布尔和复数)、变量赋值、类型转换和默认值。文章还涉及条件分支(if和switch)和循环结构(for)。最后,简要提到了Go函数的定义和多返回值特性,以及一些常见的Go命令。作者计划在后续文章中进一步探讨Go语言的其他方面。
12 0
|
7天前
|
JavaScript 前端开发 Go
Go语言的入门学习
【4月更文挑战第7天】Go语言,通常称为Golang,是由Google设计并开发的一种编程语言,它于2009年公开发布。Go的设计团队主要包括Robert Griesemer、Rob Pike和Ken Thompson,这三位都是计算机科学和软件工程领域的杰出人物。
14 1
|
7天前
|
Go