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 | ~/.m2/repository/mysql ᐅ tree -d |
python 的
1 | ~/pyenv1/lib/python2.7/site-packages ᐅ tree mycli |
go 的
1 | ~/.global_gopath ᐅ tree |
那么就会引出一个问题,如果我有2个项目,他们分别依赖相同依赖的 不同版本, 怎么解决?
java,ruby
非常简单,比如java的话如果我用maven 的话,不同的项目配置不同版本就行了,maven 会帮我下载到不同的目录下,不同的项目,引用不同classpath下的jar
python
也就是说,我对这2个项目分别提供不同的独立的python环境,不同的项目使用不同的环境。
比如以下 2个 环境 pyenvlivethriftpy
和 pyenv1
1 | ~/pyenvlivethriftpy ᐅ tree -L 1 |
1 | ~/pyenv1 ᐅ tree -L 1 |
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 | ~/.global_gopath ᐅ tree -L 1 |
set GOPATH:
1 | export GOPATH=`pwd`:/Users/caorong/.global_gopath |
这样,global_gopath 里没有的依赖才会下载到项目本地。
idea-go 的坑
我最终使用 idea 是因为看别人的代码的话,show caller of method 'xxx'
这个功能太好用.
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 | GOROOT=/usr/local/Cellar/go/1.6.2/libexec |
如果, 画蛇添足这么搞 go build -o cow main.go
go 会忽略中间,相当于执行 go run main.go
, 至少我这个版本是这样的。。