go 入门-环境

最近,为了确认家里的cow 是什么原因总有些卡顿,在看 cow 的源码,顺便改下代码.

由于单个文件的代码行数非常多,并且 vim-go 没有 show caller of method 'xxx', ag 匹配出来的太多,也不方便看

然后就调研了下 vscode-go, 以及 idea-go-plugin

基本功能支持

首先, auto-completeion, errorcheck 等基本功能都支持

但是 vscode-go 和 idea-go-plugin 都不支持 show caller of method 'xxx' 的功能, 这个功能只有 idea 支持,并且 debug 的话也是 idea 最容易使用。

GOPATH

这里先扯一下 GOPATH,golang 和 python, nodejs 一样目前流行的 build tool 都是没有提供基于版本区分的 依赖仓库,只有一个全局仓库。

而类似 java, ruby 有对版本作区分。

举个例子

java的 mvn 仓库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
~/.m2/repository/mysql ᐅ tree -d
.
└── mysql-connector-java
├── 5.1.18
├── 5.1.21
├── 5.1.25
├── 5.1.29
├── 5.1.31
├── 5.1.32
├── 5.1.33
├── 5.1.34
├── 5.1.35
├── 5.1.36
├── 5.1.37
├── 5.1.38
├── 5.1.39
└── 5.1.6

python 的

1
2
3
4
5
6
7
8
9
10
11
~/pyenv1/lib/python2.7/site-packages ᐅ tree mycli
mycli
├── __init__.py
├── __init__.pyc
├── clibuffer.py
├── clibuffer.pyc
├── clistyle.py
├── clistyle.pyc
├── clitoolbar.py
├── clitoolbar.pyc
...

go 的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
~/.global_gopath ᐅ tree
.
├── bin
│   ├── goimports
│   └── gotype
├── pkg
│   └── darwin_amd64
│   └── golang.org
│   └── x
│   └── tools
│   ├── go
│   │   └── ast
│   │   └── astutil.a
│   └── imports.a
└── src
└── golang.org
└── x
└── tools
├── AUTHORS
├── CONTRIBUTING.md
├── CONTRIBUTORS
├── LICENSE
├── PATENTS
├── README
├── benchmark
│   └── parse
│   ├── parse.go
...

那么就会引出一个问题,如果我有2个项目,他们分别依赖相同依赖的 不同版本, 怎么解决?

java,ruby

非常简单,比如java的话如果我用maven 的话,不同的项目配置不同版本就行了,maven 会帮我下载到不同的目录下,不同的项目,引用不同classpath下的jar

python

Virtualenv

也就是说,我对这2个项目分别提供不同的独立的python环境,不同的项目使用不同的环境。

比如以下 2个 环境 pyenvlivethriftpypyenv1

1
2
3
4
5
6
7
8
9
10
11
~/pyenvlivethriftpy ᐅ tree -L 1
.
├── bin
├── include
├── lib
└── pip-selfcheck.json

3 directories, 1 file

~/pyenvlivethriftpy ᐅ ls lib/python2.7/site-packages/requests
requests/ requests-2.7.0.dist-info/
1
2
3
4
5
6
7
8
9
10
11
~/pyenv1 ᐅ tree -L 1
.
├── bin
├── include
├── lib
├── man
├── pip-selfcheck.json
└── share

~/pyenv1 ᐅ ls lib/python2.7/site-packages/requests
requests/ requests-2.9.1.dist-info/

python 的依赖管理就是不管理,全部全局化,带来的问题是增加了很多冗余的依赖。

node

node 我不是很熟悉,我只知道 npm 可以 通过 -g 支持自己选择安装到全局 或者安装到项目目录。

目录名为 node_modules

但是我的 hexo 就无法使用 global 的仓库,我也不知道为什么,官方issue 建议 装到自己项目目录。。

感觉这个 -g 有些鸡肋。。。

go

go 为了解决上面的问题,引入了 GOPATH 的东东。

GOPATH 配置了,本项目的依赖从什么地方找,或者 go get 将依赖下载到什么地方。

go 下载的依赖全部依托于git,他其实是 git clone 了项目的master分支,到本地 src 目录下。

然后利用git 的 tag 或者分支,选版本(依赖的开发者自己定义)

这个设计的初衷我猜是为了更方便的使用新版本或 unrelease 的版本, 但是规范不太统一,(有的人可能只有一个master 分支).

像 java 的话, 如果我像用 milestone 的 spring 版本,我还得配置spring 自己的仓库地址,如果想用 master 分支的内容,还得自己打包什么的太麻烦了。

GOPATH 还可以配置多个path,以便解决冗余依赖的问题。

go 目前的ide 的 code-completeion, error-check, goto-definition 等功能都是需要 GOPATH 下有对应的依赖。

那么如果,我们每个项目都仅仅如下配置 GOPATH

1
export GOPATH=`pwd`

那么如果你使用的是 vscode-go 作为ide的话就操蛋了,因为你的每个项目都要 go get 一遍冗余的工具 (关键的问题是慢!)

我目前是将 类似通用的 go tools 放在 全局 GOPATH

1
2
3
4
5
~/.global_gopath ᐅ tree -L 1
.
├── bin
├── pkg
└── src

set GOPATH:

1
export GOPATH=`pwd`:/Users/caorong/.global_gopath

这样,global_gopath 里没有的依赖才会下载到项目本地。

idea-go 的坑

我最终使用 idea 是因为看别人的代码的话,show caller of method 'xxx' 这个功能太好用.

自己写代码的话,直接用 vim-go 加上 ag 就足够了

go 的代码可以将本该 写在一个 .go 文件内的多个方法 分拆到多个 .go 文件内,只要他们都在一个 package 下

具体的例子可以看这里的 issue

也就是说,有些源码 如果是这种 multi file 的project 的话,idea-go 是没法直接跑的。

也就是他不能 go run xx.go, 但是 他可以 go run *.go 或者 go build -o xx && ./xx

但是 idea-go 现在提供了一种方法,使用的就是上面的最后一个方式,先build 出二进制,然后运行, 并且捕捉 stdout 到 ide。

ps: debug 也是类似的,编译一个带远程调试接口的二进制,然后远程调试.

这里有个坑就是, 比如 cow 这种 multi file 的项目,不用在意ide 的错误。

run kind 选 file / package 都一样不填

1.png

真正执行的命令是

1
2
3
GOROOT=/usr/local/Cellar/go/1.6.2/libexec
GOPATH=/Users/caorong/Documents/workspace_go/cow:/Users/caorong/.global_gopath
/usr/local/Cellar/go/1.6.2/libexec/bin/go build -o /private/var/folders/8x/b368c6396bvc5862_gqq06rw0000gn/T/cowgo ""

如果, 画蛇添足这么搞 go build -o cow main.go go 会忽略中间,相当于执行 go run main.go , 至少我这个版本是这样的。。

avatar

lelouchcr's blog