# A Quick Guide for Go Modules

## 写在前面

在编译frp项目的时候，它依赖的golang相关库在下载时被墙了，导致编译中止。根据以往的经验，尝试手动把相关依赖`git clone`到`GOPATH`后继续编译，但是仍然失败。

打开源码目录，发现一个`go.mod`的文件，查了下资料才明白原来这是Go1.11的一个新特性——`Go Modules`，也就是**Go**的包依赖管理。

## 快速开始

在`GOPATH`目录外创建一个新目录：

```
$ mkdir -p /tmp/scratchpad/hello
$ cd /tmp/scratchpad/hello
```

初始化一个新模块：

```
$ go mod init github.com/you/hello
go: creating new go.mod: module github.com/you/hello
```

写段测试代码：

```
$ cat <<EOF > hello.go
package main

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Hello())
}
EOF
```

编译：

```
$ go build
go: golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c: unrecognized import path "golang.org/x/text" (https fetch: Get https://golang.org/x/text?go-get=1: dial tcp 216.239.37.1:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has
failed to respond.)
go: error loading module requirements
```

不妙，被墙了。幸好`Go Modules`支持`replace`命令，提供导入另一个路径，可以是位于VCS (GitHub或其他地方)中的另一个模块，或者是本地的绝对、相对路径。

编辑`go.mod`文件，用github仓库代替golang：

```
cat go.mod
module github.com/kysonlok/hello

go 1.12

// Add replace directive in here
replace (
        golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c => github.com/golang/text v0.0.0-20170915032832-14c0d48ead0c
)
```

重新编译并运行：

```
$ go build
$ .\hello.exe
你好，世界。
```

`go.mod`文件会自动被更新，而且包含了依赖的明确依赖信息：

```
$ cat go.mod
module github.com/kysonlok/hello

go 1.12

replace golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c => github.com/golang/text v0.0.0-20170915032832-14c0d48ead0c

require rsc.io/quote v1.5.2
```

有了`Go Modules`以后，工作流应该变成这样：

* 在.go文件用import导入依赖
* 执行标准命令`go build`或者`go test`，将会自动更新`go.mod`，并且下载依赖
* 当需要指定依赖版本的时候，可以执行诸如这样的命令`go get foo@v1.2.3`, `go get foo@master`, `go get foo@e3702bed2`，或者直接编辑`go.mod`文件

简单介绍我们可能常会用到的功能：

* `go list -m all`: 查看构建中直接或者间接依赖的packages的当前版本 &#x20;
* `go list -u -m all`: 查看直接或者间接依赖的packages的最新版本 &#x20;
* `go get -u` or `go get -u=patch`: 更新直接或者间接依赖的pakages到最新版本 &#x20;
* `go build ./...` or `go test ./...`: 在模块的跟目录执行时，构建并且测试模块中的所有pakages &#x20;
* `go mod tidy`: 从`go.mod`中删除任何不再需要的依赖项 &#x20;
* `replace指令` or `gohack`: 用另外一个版本代替自动推导的版本，可以是源于不同的repo &#x20;
* `go mod vendor`: 创建**vendor**目录，并且把直接或者间接依赖的packages复制到该目录下   &#x20;

好了，先Mark到这里。

## See also

[Go Modules](https://github.com/golang/go/wiki/Modules)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kysonlok.gitbook.io/blog/go/modules.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
