Golang依赖管理工具: go module (go1.11+)

大多数语言都会有包管理工具,像Node有npm,PHP有composer,Java有MavenGradle

可是,Go语言一直缺乏一个官方的包管理(之前有个Dep被称为官方试验品official experiment)。

终于,在2018年发布的go1.11 版本中,新增了go module管理模块功能,用来管理依赖包。

要知道,在这个之前,想要对go语言包进行管理,只能依赖第三方库实现,比如Vendor,GoVendor,GoDep,Dep,Glide等等,对于初学者来说,真的是选择困难症。

关于Workspaces和GOPATH

go1.11 之前,如果不使用第三方包管理工具可行,就是直接使用go get安装第三方包。

工作空间Workspaces,是Go项目的根目录,也就是 GOPATH是GO项目必备的环境变量,用来存放Go的开发代码和第三方包代码,代码需要按照一定的目录安排。

指定GOPATH路径:

$ echo $HOME
/Users/wangtom $ export GOPATH=$HOME/go

查看GOPATH:

$ go env |grep GOPATH
GOPATH="/Users/wangtom/go"

开启 GO111MODULE:

要使用 go module, 需要先设置 GO111MODULE 环境变量,即设置GO111MODULE=on。如果没设置,执行命令的时候会有提示。

# 使用 go 命令设置
$ go env -w GO111MODULE=on # linux / mac
$ export GO111MODULE=on $ go env |grep GO111MODULE
GO111MODULE="on"

从 Go1.13 版本开始,go module 成为了Go语言默认的依赖管理工具,不需要再手动设置 GO111MODULE=on 了。

这是因为,默认设置的GO111MODULE=auto, 导致 modules 默认在 GOPATH/src 路径下是不启用的。

如果需要在 GOPATH/src 也能使用modules, 需要把 GO111MODULE 环境变量设置为 on.

$ export GO111MODULE=on
$ go mod init github.com/cnwyt/mylib
go: creating new go.mod: module github.com/cnwyt/mylib

创建一个公用模块 mylib 模块

创建一个公共模块mylib:

模块命名为 github.com/cnwyt/mylib,就是我们创建的GitHub仓库的路径,方便我们以后提交代码、供别人的调用。

(1)按照原来GOPATH开发模式,创建新的包需要放置在 $GOPATH/src/github.com

创建一个目录mylib目录,并进入该命令:

$ mkdir -p $GOPATH/src/github.com/cnwyt/mylib
$ cd $GOPATH/src/github.com/cnwyt/mylib

(2)使用 go mod init 命令初始化:

随便找一个目录,比如在 ~/dev/go-demo:

$ mkdir mylib
$ cd mylib
$ go mod init github.com/cnwyt/mylib
go: creating new go.mod: module github.com/cnwyt/mylib $ ls
go.mod $ cat go.mod
module github.com/cnwyt/mylib
go 1.19

初始化后,会生成一个go.mod文件,类似 npm 里的 package.json 或者 composer 的 composer.json 的一个文件。

创建一个名为util的公共包,公共包我们一般放置放在项目的 pkg 目录下:

# mylib/pkg/util/hello.go
package util import "fmt" func SayHello() {
fmt.Println("nihao -- from mylib")
}

在main函数中调用,

package main

import (
"fmt" // <----- 这里引入本项目的 utl 包
// 路径与使用 go mod init初始化时的 module 名称一致
"github.com/cnwyt/mylib/pkg/util"
) func main() {
fmt.Println("Hello, mylib!") // <----- 这里调用本项目的 utl 包的方法
util.SayHello()
}

常用的go mod命令如下表所示:

命令 作用
go mod init 初始化当前文件夹,创建 go.mod 文件
go mod edit 编辑 go.mod 文件
go mod tidy 增加缺少的包,删除无用的包
go mod download 下载依赖包到本地(默认在 GOPATH/pkg/mod 目录)
go mod graph 打印模块依赖图
go mod vendor 将依赖复制到 vendor 目录下
go mod verify 校验依赖
go list -m all 查看所有的依赖

创建一个本地模块 appdemo , 并调用 mylib:

在 GOPATH 以外的目录里,创建一个 appdemo 的应用目录,作为自己的项目目录。

因为作为应用目录不需要别人调用,不需要放到网上,因此不加 github.com 域名,直接起个 mod 名字即可,这里起的名字是 appdemo,和该项目的目录同名。

$ mkdir appdemo && cd appdemo

$ go mod init appdemo
go: creating new go.mod: module appdemo $ vi main.go

创建一个 main.go 文件:

package main

import "fmt"

func main() {
fmt.Println("Hello, appdemo!");
}

在 appdemo 项目,我们也创建一个名为 util 的公共包(该包仅供该项目里共用),公用包我们一般放置放在项目的 pkg 目录下:

# mylib/pkg/util/hello.go
package util import "fmt" // UnixTime time()
func UnixTime() int64 {
return time.Now().Unix()
}

在 main.go 里调用:

package main

import (
"fmt" // <----- 这里引入本项目的 utl 包
// 路径与使用 go mod init初始化时的 module 名称一致
"pkg/util"
) func main() {
fmt.Println("Hello, mylib!") // <----- 这里调用本项目的 utl 包的方法
t := util.UnixTime()
fmt.Println("timestamp: ", t)
}

调用前边的公用模块 mylib:

初始化该模块,引入github.com/cnwyt/mylib模块,指定版本为latest:

$ go mod init appdemo
$ go mod edit -require github.com/cnwyt/mylib@latest

查看 go.mod 文件。

$ cat go.mod
module appdemo go 1.19 require github.com/cnwyt/mylib v0.0.0

这样直接执行 go build 会报错:

$ go build
# <---- 可能是这个报错:
build appdemo: cannot find module for path github.com/cnwyt/mylib # <---- 可能是这个,找不到这个mylib,报错:
go: errors parsing go.mod:
Confirm the import path was entered correctly.

这是为啥呢?

这是因为我们虽然创建了一个名为 github.com/cnwyt/mylib 公用模块,在GOPATH路径里没有这个模块。go mod 去 Github 去找这个模块找不到(还没推送到远程)。

那该怎么办呢?

有两个解决办法: 第一个办法,很简单,就是直接将cnwyt/mylib模块推送的 GitHub上。但是,如果我要修改cnwyt/mylib里的代码,每次都得先推送到GitHub上,才能生效,实在太麻烦了。

那就直接使用第二个办法, 使用 go replace 临时替代:

可以使用 go mod edit 命令修改。或直接修改 go.mod 文件,新增一行 replace:

module helloworld

require github.com/cnwyt/mylib v0.0.0

replace github.com/cnwyt/mylib => /Users/wangtom/dev/go-example/go-mod-demo/mylib

注意版本号必须填写,格式为 v1.2.3, 可以填v0.0.0.

package main

import (
"appdemo/pkg/util"
"fmt" // <----- 这里引入 公共模块 mylib 的 util 包
// <----- 因为与项目里的util包重名了,所以重命名为 util2
util2 "github.com/cnwyt/mylib/pkg/util"
) func main() {
fmt.Println("hello app demo")
timestamp := util.UnixTime() fmt.Println("timestamp: ", timestamp) // <----- 这里调用 公共模块 mylib
util2.SayHello()
}

然后重新运行,可以看到可以正常调用 mylib 里的方法:

$ go run main.go
hello app demo
timestamp: 1666147320
nihao -- from mylib

调用已存在的第三方模块

这里演示调用第三方模块 Redis 操作库 go-redis/redis。

使用 go get 下载安装 go-redis/redis:

$ go get github.com/go-redis/redis/v8

go: added github.com/cespare/xxhash/v2 v2.1.2
go: added github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
go: added github.com/go-redis/redis/v8 v8.11.5

运行 go buildgo test 会自动从GitHub下载模块,并会修改 go.mod 文件。

如果下载不下来代码,可以设置goproxy模块代理(七牛云提供)。

# Go 1.13 及以上(推荐)
# 打开你的终端并执行 $ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct

查看 go.mod 文件变化:

module appdemo

go 1.19

require github.com/cnwyt/mylib v0.0.0

require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
) replace github.com/cnwyt/mylib => /Users/wangtom/dev/go-example/go-mod-demo/mylib

使用 go mod 下载安装的模块,代码会放到 $GOPATH/pkg/mod/ 目录下:


$ ls $GOPATH/pkg/mod/github.com/go-redis
redis
redis@v6.15.9+incompatible

代码示例:

import (
"context"
"github.com/go-redis/redis/v8"
"fmt"
) var ctx = context.Background() func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
}) err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
} val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key", val) val2, err := rdb.Get(ctx, "key2").Result()
if err == redis.Nil {
fmt.Println("key2 does not exist")
} else if err != nil {
panic(err)
} else {
fmt.Println("key2", val2)
}
// Output: key value
// key2 does not exist
}

参考链接

https://wang123.net/a/golang-go-mod-intro

END

Golang依赖管理工具: go module 详解的更多相关文章

  1. redis cluster管理工具redis-trib.rb详解

    redis cluster管理工具redis-trib.rb详解 来源 http://weizijun.cn/2016/01/08/redis%20cluster%E7%AE%A1%E7%90%86% ...

  2. Golang依赖管理工具:glide从入门到精通使用

    这是一个创建于 2017-07-22 05:33:09 的文章,其中的信息可能已经有所发展或是发生改变. 介绍 不论是开发Java还是你正在学习的Golang,都会遇到依赖管理问题.Java有牛逼轰轰 ...

  3. 进程管理工具之supervisor[详解]

    原文链接:https://blog.csdn.net/weixin_42390791/article/details/88866237 一.问题背景1.背景​   如何才能让一个进程摆脱终端,获得相对 ...

  4. golang多个项目时如何配置GOPATH,使用gb包依赖管理工具,不同项目配置不同的GOPATH的

    golang多个项目时如何配置GOPATH,使用gb包依赖管理工具,不同项目配置不同的GOPATH的 1:执行脚本setGoPath.sh#!/bin/bashif [[ $GOPATH =~ .*$ ...

  5. 黑苹果引导工具 Clover 配置详解及Clover Configurator使用

    黑苹果引导工具 Clover 配置详解及Clover Configurator使用  2017-03-11 14:01:40 by SemiconductorKING 转自:@三个表哥   简介: 可 ...

  6. Go依赖管理及Go module使用

    Go语言的依赖管理随着版本的更迭正逐渐完善起来. 依赖管理 为什么需要依赖管理 最早的时候,Go所依赖的所有的第三方库都放在GOPATH这个目录下面.这就导致了同一个库只能保存一个版本的代码.如果不同 ...

  7. golang包管理工具

    软件开发中,不可避免的会使用到第三方库,因此包管理工具可以极大的方便开发者管理第三方依赖,避免掉入"依赖地狱". 作为google强大背书的golang语言,golang官方包管理 ...

  8. 日志分析工具ELK配置详解

    日志分析工具ELK配置详解 一.ELK介绍 1.1 elasticsearch 1.1.1 elasticsearch介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分 ...

  9. KVM镜像管理利器-guestfish使用详解

    原文  http://xiaoli110.blog.51cto.com/1724/1568307   KVM镜像管理利器-guestfish使用详解 本文介绍以下内容: 1. 虚拟机镜像挂载及w2k8 ...

  10. Go 包依赖管理工具 —— govendor

    govendor 是一个基于 vendor 机制实现的 Go 包依赖管理命令行工具.与原生 vendor 无侵入性融合,也支持从其他依赖管理工具迁移,可以很方便的实现同一个包在不同项目中不同版本.以及 ...

随机推荐

  1. python之路30 网络编程之初识并发编程1

    并发编程理论 研究网络编程其实就是在研究计算机的底层原理及发展史 """ 计算机中真正干活的是CPU """ 操作系统发展史 1.穿孔卡片阶 ...

  2. ClickHouse ORM 3.x 发布啦

    经过1年断断续续的迭代,ClickHouse ORM 3.x 发布啦-说说它的故事吧. 回顾下2022 说来惭愧上次写博客都是22年4月份了,今年行情不好团队急剧收缩,工作几乎全扑在接手存量业务和主业 ...

  3. awk 入门

    参考资料:awk从放弃到入门(1):awk基础 (通俗易懂,快进来看)-朱双印博客 (zsythink.net) awk系列博文直达链接:AWK命令总结之从放弃到入门 我们先来用专业的术语描述一下aw ...

  4. Cert Manager 申请 SSL 证书流程及相关概念 - 一

    2022.3.9 用 cert-manager 申请成功通配符证书 (*.ewhisper.cn), 2022.4.30 该证书距离过期还有 30 天,cert-manager 进行自动续期,但是却失 ...

  5. 对象的变为私有方法不可改动 seal freeze

  6. Windows10下yolov8 tensorrt模型加速部署【实战】

    Windows10下yolov8 tensorrt模型加速部署[实战] TensorRT-Alpha基于tensorrt+cuda c++实现模型end2end的gpu加速,支持win10.linux ...

  7. 在 MBP(Apple M1 Pro)上捣鼓友善 nanoPi R5S——【一、构建 rkdeveloptool】

    在种草了很多天之后,最近终于在淘宝下单了友善 nanoPi R5S. 选择友善 nanoPi R5S 有两点主要理由: 1. 自带 EMMC 存储,可以使用 RockChip 提供的 MaskRom ...

  8. chatGPT 桌面版安装教程

    概述 标题党了,首先声明 ChatGPT 官方没有桌面版,目前市面上很多的桌面应用也在是浏览器上包了一层,而且大多做的比较粗糙,不太好用,所以都不太推荐. 作为一名骨灰级的程序员,ChatGPT 的重 ...

  9. 洛谷 P3916 图的遍历

    题目链接 最容易想的思路:对于每一个点都进行dfs/bfs,时间复杂度为O(n*(n+m)),显然超时 可以使用类似记忆化的操作,一个点能到达的最大值是自己所有能达到的边的最大值,则可以递归来做 但有 ...

  10. Django-Django基本使用、app、三板斧

    1.纯手撸web框架 1.web框架的本质 理解1:连接前端与数据库的中间介质 理解2:socket服务端 2.手写web框架 1.编写socket服务端代码 2.浏览器访问响应无效>>& ...