go modules 是 golang 1.11 新加的特性。现在1.12 已经发布了,是时候用起来了。Modules官方定义为:

模块是相关Go包的集合。modules是源代码交换和版本控制的单元。 go命令直接支持使用modules,包括记录和解析对其他模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。

如何使用 Modules ?

  1. 把 golang 升级到 1.11(现在1.12 已经发布了,建议使用1.12)
  2. 设置 GO111MODULE

GO111MODULE

GO111MODULE 有三个值:off, onauto(默认值)

  • GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
  • GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。
  • GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
    • 当前目录在GOPATH/src之外且该目录包含go.mod文件
    • 当前文件在包含go.mod文件的目录下面。

当modules 功能启用时,依赖包的存放位置变更为$GOPATH/pkg,允许同一个package多个版本并存,且多个项目可以共享缓存的 module。

go mod

golang 提供了 go mod命令来管理包。

go mod 有以下命令:

命令 说明
download download modules to local cache(下载依赖包)
edit edit go.mod from tools or scripts(编辑go.mod
graph print module requirement graph (打印模块依赖图)
init initialize new module in current directory(在当前目录初始化mod)
tidy add missing and remove unused modules(拉取缺少的模块,移除不用的模块)
vendor make vendored copy of dependencies(将依赖复制到vendor下)
verify verify dependencies have expected content (验证依赖是否正确)
why explain why packages or modules are needed(解释为什么需要依赖)

如何在项目中使用

示例一:创建一个新项目

  1. GOPATH 目录之外新建一个目录,并使用go mod init 初始化生成go.mod 文件
➜  ~ mkdir hello
➜ ~ cd hello
➜ hello go mod init hello
go: creating new go.mod: module hello
➜ hello ls
go.mod
➜ hello cat go.mod
module hello go 1.12
复制代码

go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。

go.mod 提供了module, requirereplaceexclude 四个命令

  • module 语句指定包的名字(路径)
  • require 语句指定的依赖项模块
  • replace 语句可以替换依赖项模块
  • exclude 语句可以忽略依赖项模块
  1. 添加依赖

新建一个 server.go 文件,写入以下代码:

package main

import (
"net/http" "github.com/labstack/echo"
) func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":1323"))
}
复制代码

执行 go run server.go 运行代码会发现 go mod 会自动查找依赖自动下载:

$ go run server.go
go: finding github.com/labstack/echo v3.3.10+incompatible
go: downloading github.com/labstack/echo v3.3.10+incompatible
go: extracting github.com/labstack/echo v3.3.10+incompatible
go: finding github.com/labstack/gommon/color latest
go: finding github.com/labstack/gommon/log latest
go: finding github.com/labstack/gommon v0.2.8
# 此处省略很多行
... ____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:1323
复制代码

现在查看go.mod 内容:

$ cat go.mod

module hello

go 1.12

require (
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/gommon v0.2.8 // indirect
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/valyala/fasttemplate v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
)
复制代码

go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit,详见 Modules官方介绍。 go 会自动生成一个 go.sum 文件来记录 dependency tree:

$ cat go.sum
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
... 省略很多行
复制代码
  1. 再次执行脚本 go run server.go 发现跳过了检查并安装依赖的步骤。
  2. 可以使用命令 go list -m -u all 来检查可以升级的package,使用go get -u need-upgrade-package 升级后会将新的依赖版本更新到go.mod * 也可以使用 go get -u 升级所有依赖

go get 升级

  • 运行 go get -u 将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
  • 运行 go get -u=patch 将会升级到最新的修订版本
  • 运行 go get package@version 将会升级到指定的版本号version
  • 运行go get如果有版本的更改,那么go.mod文件也会更改

示例二:改造现有项目(helloword)

项目目录为:

$ tree
.
├── api
│ └── apis.go
└── server.go 1 directory, 2 files
复制代码

server.go 源码为:

package main

import (
api "./api" // 这里使用的是相对路径
"github.com/labstack/echo"
) func main() {
e := echo.New()
e.GET("/", api.HelloWorld)
e.Logger.Fatal(e.Start(":1323"))
}
复制代码

api/apis.go 源码为:

package api

import (
"net/http" "github.com/labstack/echo"
) func HelloWorld(c echo.Context) error {
return c.JSON(http.StatusOK, "hello world")
}
复制代码
  1. 使用 go mod init *** 初始化go.mod
$ go mod init helloworld
go: creating new go.mod: module helloworld
复制代码
  1. 运行 go run server.go
go: finding github.com/labstack/gommon/color latest
go: finding github.com/labstack/gommon/log latest
go: finding golang.org/x/crypto/acme/autocert latest
go: finding golang.org/x/crypto/acme latest
go: finding golang.org/x/crypto latest
build command-line-arguments: cannot find module for path _/home/gs/helloworld/api
复制代码

首先还是会查找并下载安装依赖,然后运行脚本 server.go,这里会抛出一个错误:

build command-line-arguments: cannot find module for path _/home/gs/helloworld/api
复制代码

但是go.mod 已经更新:

$ cat go.mod
module helloworld go 1.12 require (
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/gommon v0.2.8 // indirect
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/valyala/fasttemplate v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
)
复制代码
那为什么会抛出这个错误呢?

这是因为 server.go 中使用 internal package 的方法跟以前已经不同了,由于 go.mod会扫描同工作目录下所有 package 并且变更引入方法,必须将 helloworld当成路径的前缀,也就是需要写成 import helloworld/api,以往 GOPATH/dep 模式允许的 import ./api 已经失效,详情可以查看这个 issue

  1. 更新旧的package import 方式

所以server.go 需要改写成:

package main

import (
api "helloworld/api" // 这是更新后的引入方法
"github.com/labstack/echo"
) func main() {
e := echo.New()
e.GET("/", api.HelloWorld)
e.Logger.Fatal(e.Start(":1323"))
}
复制代码

一个小坑:开始在golang1.11 下使用go mod 遇到过 go build github.com/valyala/fasttemplate: module requires go 1.12 这种错误,遇到类似这种需要升级到1.12 的问题,直接升级golang1.12 就好了。幸亏是在1.12 发布后才尝试的go mod

go mod 使用的更多相关文章

  1. 函数mod(a,m)

    Matlab中的函数mod(a,m)的作用: 取余数 例如: mod(25,5)=0; mod(25,10)=5; 仅此.

  2. ORACLE 数据库 MOD 函数用法

    1.求2和1的余数. Select mod(2,1) from dual: 2能被1整除所以余数为0. 2.MOD(x,y)返回X除以Y的余数.如果Y是0,则返回X的值. Select mod(2,0 ...

  3. 黑科技项目:英雄无敌III Mod <<Fallen Angel>>介绍

    英雄无敌三简介(Heroes of Might and Magic III) 英3是1999年由New World Computing在Windows平台上开发的回合制策略魔幻游戏,其出版商是3DO. ...

  4. [日常训练]mod

    Description 给定$p_1,p_2,-,p_n,b_1,b_2,...,b_m$, 求满足$x\;mod\;p_1\;\equiv\;a_1,x\;mod\;p_2\;\equiv\;a_2 ...

  5. Apache Mod/Filter Development

    catalog . 引言 . windows下开发apache模块 . mod进阶: 接收客户端数据的 echo 模块 . mod进阶: 可配置的 echo 模块 . mod进阶: 过滤器 0. 引言 ...

  6. FZU 1752 A^B mod C(快速加、快速幂)

    题目链接: 传送门 A^B mod C Time Limit: 1000MS     Memory Limit: 65536K 思路 快速加和快速幂同时运用,在快速加的时候由于取模耗费不少时间TLE了 ...

  7. HDOJ 4389 X mod f(x)

    数位DP........ X mod f(x) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...

  8. hdu.1104.Remainder(mod && ‘%’ 的区别 && 数论(k*m))

    Remainder Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  9. 对于一个负数mod正数

    鸟神说.. a/b靠零取整 然后呢..a%b定义成a-(a/b)*b c语言就是这么算的... 那么python2.6是怎么算的呢 如果最后你取模想得到一个正数.. 那么在上述取模定义不变的情况下 p ...

  10. 51Nod 1046 A^B Mod C Label:快速幂

    给出3个正整数A B C,求A^B Mod C.   例如,3 5 8,3^5 Mod 8 = 3. Input 3个正整数A B C,中间用空格分隔.(1 <= A,B,C <= 10^ ...

随机推荐

  1. centos删除指定名称的进程

    vim kill_process.sh ----------------------------------- if [ "$1" = "" ]; then e ...

  2. Linux内核device结构体分析

    1.前言 Linux内核中的设备驱动模型,是建立在sysfs设备文件系统和kobject上的,由总线(bus).设备(device).驱动(driver)和类(class)所组成的关系结构,在底层,L ...

  3. 在博文顶部添加文章字数及阅读时间信息:阅读本文需要xx分钟

    1.在博客园设置中,页首Html代码中添加js代码 2.js代码如下 <script type="text/javascript"> $("#cnblogs_ ...

  4. xunsearch搜索测试

    1.导入测试数据 cd $prefix/sdk/php util/Indexer.php --source=csv --clean demo 然后出现 初始化数据源 ... csv WARNING: ...

  5. 【源码阅读】SpringBoot-v2.2.0启动过程以及细节

    启动流程 图如下: 以上流程图源文件(可导入https://www.processon.com):https://github.com/Mysakura/DataFiles 相关Event(org.s ...

  6. Android开发遇到的一些小问题

    1.文件下载时,默认只能用https,怎么用http协议: 在Manifest.xml文件中增加一个配置项: android:usesCleartextTraffic="true" ...

  7. Java学习:数据结构简介

    数据结构 数据结构: 数据结构_栈:先进后出 入口和出口在同一侧 数据结构_队列:先进先出 入口和出口在集合的两侧 数据结构_数组: 查询快:数组的地址是连续的,我们通过数组的首地址可以找到数组,通过 ...

  8. -UI调试工具 SAK 布局 MD

    目录 目录 SwissArmyKnife 接入方式 自动初始化版本 支持的功能 可配置项 原理 自定义功能 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndro ...

  9. javascript异步编程学习及实例

    所谓异步就是指给定了一串函数调用a,b,c,d,各个函数的执行完结返回过程并不顺序为a->b->c->d(这属于传统的同步编程模式),a,b,c,d调用返回的时机并不确定. 对于js ...

  10. HTML列表简单介绍

    1.无序列表 使用标签:<ul>,<li> 属性:disc,circle,square 2.有序列表 使用标签:<ol>,<li> 属性:A,a,I,i ...