英文:
Automatically define GOPATH on a per project basis
问题
对于我创建的每个项目,每次进入项目目录时,我都必须执行export GOPATH={path_to_project}
。肯定有更简单的方法。难道我不能为给定的目录创建一个.bashrc或.bash_profile文件来定义该项目的GOPATH吗?
例如,我有两个Go项目A和B。如果我有一个统一的GOPATH,在我在项目之间移动时不重新定义,那么两个项目的二进制文件将存储在同一个位置。更重要的是,第三方库的二进制文件也将存储在同一个位置,因此我无法在每个项目的基础上维护同一库的多个版本。
然而,如果我能够按项目定义GOPATH,那么所有的二进制文件和第三方库都将与项目相关。这似乎是大多数其他语言环境中处理包管理的常见方式(如Ruby的rbenv,Python的vertiualenv等)。
英文:
For every project I create, I have to do export GOPATH={path_to_project}
every time I cd into the project dir. There has to be an easier way. Isn't there some way I can create a .bashrc or .bash_profile file for a given directory to define the GOPATH for that project?
For example, I have two go projects A and B. If I have a singular GOPATH that isn't redefined when I move between projects, then binaries for both projects will be stored in the same place. More importantly, binaries for third party libraries will be stored in the same place, so I have no way of maintaining multiple versions of the same library on a per project basis.
However, if I am able to define GOPATH on a per project basis, then all binaries and third party libraries are project dependent. This seems to be the common way of handling package management in most other language environments (ruby rbenv, python vertiualenv, etc.)
答案1
得分: 25
(Q2 2018:
请注意,随着vgo(现在称为“module”)项目的推出,GOPATH
可能会被弃用,取而代之的是基于项目的工作流程。这将避免我在两年前提出的手动项目GOPATH
。
在Go 1.11(2018年8月)中,GOPATH
可以是可选的,使用模块。
您在使用便捷管理多个GOPATH目录中表达了类似的想法,由Herbert Fischer (hgfischer
)提出,适用于Linux/Unix环境(基于上面评论中提到的问题):
> 只需将以下代码片段包含在您的~/.bashrc
(或~/.bash_profile
)中,并使用source ~/.bashrc
重新加载您的shell环境。
此代码片段将创建一个shell函数,该函数将覆盖内置命令cd
,并使用自定义命令扫描输入的目录以及上层目录,查找名为.gopath
的文件。
cd () {
builtin cd "$@"
cdir=$PWD
while [ "$cdir" != "/" ]; do
if [ -e "$cdir/.gopath" ]; then
export GOPATH=$cdir
break
fi
cdir=$(dirname "$cdir")
done
}
> 现在您只需要在您想要作为GOPATH
的每个目录中创建一个.gopath
文件,每次进入该目录时,重新定义的cd
函数将将当前环境的GOPATH
设置为该目录。
2017年更新:如果您不想修改您的环境,您仍然可以通过在Visual Studio Code(一个跨平台的IDE)中打开该项目的src
文件夹来为每个项目使用一个GOPATH
,并结合扩展程序“Go for Visual Studio Code”。
在该IDE中,您可以:
- 在名为
go.toolsGopath
的设置中保留您的全局唯一GOPATH
。 - 使用名为
go.inferGopath
的设置推断您当前的GOPATH
。
这样,VSCode将在您的全局GOPATH
中安装一系列工具(供您在VSCode之外使用)。
请参阅“Go extension依赖的Go工具”:godep
,golint
,guru
,godoc
等。
而对于您的项目,GOPATH
将是src文件夹的父文件夹:
当您从IDE编译/安装项目时,这将起作用。
如果您想要从命令行执行此操作,则仍然适用上面的原始答案。
英文:
(Q2 2018:
Note that with the vgo (now "module") project, GOPATH
might end up being deprecated in favor of a project-based workflow. That would avoid the manual project-based GOPATH
I was proposing below, two years ago)
With Go 1.11 (August 2018), GOPATH
can be optional, with modules.
You have a similar idea expressed in Manage multiple GOPATH dirs with ease, by Herbert Fischer (hgfischer
), for a Linux/Unix environment (base on the question already mention in the comments above):
> Just include the following snippet in your ~/.bashrc
(or ~/.bash_profile
) and reload your shell environment with source ~/.bashrc
.
This snippet will create a shell function that will override the builtin command cd
with a customized one that scans the entered directory, and every other above, for a file named .gopath
.
cd () {
builtin cd "$@"
cdir=$PWD
while [ "$cdir" != "/" ]; do
if [ -e "$cdir/.gopath" ]; then
export GOPATH=$cdir
break
fi
cdir=$(dirname "$cdir")
done
}
> Now you just need to create a .gopath
file in every directory you want as your GOPATH
and every time you enter this directory, the redefined cd
function will set the GOPATH
of your current environment to this directory.
Update 2017: if you don't want to modify your environment, you can still use one GOPATH
per project, by opening the src
folder of that project in Visual Studio Code (vscode, which is a multi-platform IDE), combined with the extension "Go for Visual Studio Code".
In that IDE, you can:
- keep your global unique
GOPATH
in a setting calledgo.toolsGopath
. - infer your current
GOPATH
with a setting calledgo.inferGopath
That way, VSCode will install a collection of tools in your global GOPATH
(for you to use outside VSCode as well).
See "Go tools that the Go extension depends on": godep
, golint
, guru
, godoc
, ...
And yet, your GOPATH
for your project will be the parent folder of src:
That works when you compile/install your project from the IDE.
If you want to do it from the command line, the original answer above would still apply.
答案2
得分: 10
你可以使用类似 autoenv 的工具来设置一个脚本,当你进入特定目录时自动执行。
对于你的目的,一个示例的 /happy/go/path/yay/.env
文件可能如下所示:
export GOPATH="/happy/go/path/yay"
export PATH="$GOPATH/bin:$PATH"
英文:
You can use a tool like autoenv to set up a script that is automatically executed when you cd
into a particular directory.
For your purposes, an example /happy/go/path/yay/.env
file might look like:
export GOPATH="/happy/go/path/yay"
export PATH="$GOPATH/bin:$PATH"
答案3
得分: 5
我会编写一个脚本,可以从当前目录推断出正确的GOPATH,并将go
命令的别名设置为首先调用此脚本。例如,一个非常简单的实现:
#!/bin/bash
# infer-gopath.sh
pwd
然后,在.bash_aliases(或您保存别名的任何位置)中:
alias go='GOPATH=$(infer-gopath.sh) go'
这将将GOPATH
设置为infer-gopath.sh
输出的内容,仅用于调用go
命令,因此不会对您的shell产生任何持久影响。
英文:
I would write a script which can infer the proper GOPATH from the current directory, and then alias the go
command to first call this script. For example, a very simple implementation:
#!/bin/bash
# infer-gopath.sh
pwd
And then, in .bash_aliases (or wherever you keep your aliases):
alias go='GOPATH=$(infer-gopath.sh) go'
This sets GOPATH
to whatever infer-gopath.sh
outputs just for the invocation of the go
command, so it won't have any lasting effect on your shell.
答案4
得分: 5
我知道这不是很聪明,但我发现如果我只是进入go项目的基本目录,其中包含src、pkg和bin文件夹,我可以简单地输入:
export GOPATH=$(pwd)
就可以了,一切都很好!
英文:
I know this is not very clever but I find that if I simply go to the base directory of the go project where I have the src, pkg and bin folders I can simply type:
export GOPATH=$(pwd)
and thats it all good!
答案5
得分: 3
我的印象是,go
工具积极地不鼓励“在每个项目基础上维护同一库的多个版本”,原因是经验表明这种策略在大型代码库(如Google的代码库)上不起作用。关于包版本控制的讨论在golang-nuts上进行了很多:(搜索列表),并且似乎讨论仍然在进行中,正如Ian Lance Taylor在这个2013年6月6日的采访中所指出的(搜索词“versioning”)。
go
打包系统的设计允许每个项目都有自己的目录结构;唯一的限制是它们都需要是GOPATH
中某个目录的子目录。这样做的好处是它与版本控制系统很好地交互,只要VCS主分支始终构建。在上面引用的博客采访中,ILT建议:
> 我们在内部的做法是对导入的代码进行快照,并定期更新该快照。这样,如果API发生变化,我们的代码库不会意外中断。
将“导入的代码”替换为“我的其他库”,这似乎是一个可能性;你可以有两个go
目录,一个用于生产,一个用于开发;对于开发,你可以将开发目录放在路径的最前面,这样开发的二进制文件和库就不会污染生产目录。我不知道这是否足够。
如果你真的想为每个项目单独设置一个GOPATH
,我建议按照以下步骤进行:
1)使每个项目的GOPATH
以名为go
(或类似的)的目录结尾
2)使用类似以下的shell函数来推断GOPATH
(几乎没有经过完全测试):
gopath() {
GOPATH="$(
( while [[ $PWD != / && $(basename $PWD) != go ]]; do
cd ..
done
if [[ $PWD == / ]]; then
echo $GOPATH
else
echo $PWD
fi
))" go "$@"
}
然后,只要你的当前工作目录位于项目的代码库中,你可以使用gopath
代替go
。(更复杂的可能性可能包括使用显式提供的项目路径来推断GOPATH
。)
英文:
My impression is that the go
tool actively discourages "maintaining multiple versions of the same library on a per project basis" for the precise reason that experience has shown that that strategy doesn't work on large codebases (such as Google's). There has been quite a lot of discussion about package versioning on golang-nuts: (search the list), and it seems that the discussion is still open, as indicated by Ian Lance Taylor in this June 6, 2013 interview (search for the word "versioning").
The go
packaging system is designed to allow every project to have its own directory structure; the only restriction is that they all need to be children of (some) directory in GOPATH
. This has the advantage that it interacts well with version control systems, as long as the VCS master always builds. In the blog interview referenced above, ILT suggests:
> What we do internally is take a snapshot of the imported code, and update that snapshot from time to time. That way, our code base won't break unexpectedly if the API changes.
Substituting "my other libraries" for "the imported code", that seems like a possibility; you could have two go
directories, production and development; for development, you could put the development directory first in the path so that development binaries and libraries don't pollute the production directories. I don't know if that is sufficient.
If you really want to have a separate GOPATH
for each project, I'd suggest the following:
-
Make every project's
GOPATH
end at a directory namedgo
(or some such) -
Deduce the
GOPATH
using the something like the following shell function (almost totally untested):gopath() {
GOPATH="$(
( while [[ $PWD != / && $(basename $PWD) != go ]]; do
cd ..
done
if [[ $PWD == / ]]; then
echo $GOPATH
else
echo $PWD
fi
))" go "$@"
}
Then you can use gopath
instead of go
as long as your current working directory is somewhere inside the project's repository. (More sophisticated possibilities might include using the explicitly provided project path, if any, to deduce GOPATH
.)
答案6
得分: 1
我不能评论,但是可以根据@joshlf的答案进行扩展:
通过在GOPATH
前面添加别名go
-- 我的方法不需要你处理/创建额外的文件:
alias go='GOPATH=$(echo $(pwd)) go'
祝好!
英文:
I can't comment, but to build off the answer from @joshlf :::
alias go
by prepending the GOPATH
-- my method doesn't require you deal with/create an extra file:
alias go='GOPATH=$(echo $(pwd)) go'
cheers
答案7
得分: 0
我喜欢上面的gopath()答案的要点,但我不喜欢(a)只为go
命令设置GOPATH
(我在vim插件等中使用它),也不喜欢(b)要记住输入gopath
而不是go
这是我最终添加到我的~/.bash_profile
的内容:
export GOPATH="...一个默认路径..."
function cd() {
builtin cd $@ &&
export GOPATH="$(
( while [[ $PWD != / && $(basename $PWD) != go ]]; do
cd ..
done
if [[ $PWD == / ]]; then
echo $GOPATH
else
echo $PWD
fi
))"
}
(我还在这篇博文中详细讨论了上述内容的要求in this blog post)
英文:
I like the guts of the gopath() answer above, but I don't like (a) having the GOPATH
set only for the go
command (I use it in vim plugins, etc), nor do I like (b) having to remember to type gopath
instead of go
This is what I ultimately added to my ~/.bash_profile
:
export GOPATH="... a default path ..."
function cd() {
builtin cd $@ &&
export GOPATH="$(
( while [[ $PWD != / && $(basename $PWD) != go ]]; do
cd ..
done
if [[ $PWD == / ]]; then
echo $GOPATH
else
echo $PWD
fi
))"
}
(I also wrote up the above with a little extra discussion of requirements in this blog post)
答案8
得分: 0
我是一个Golang新手,但最好的方法可能是在每个项目中创建一个shell脚本来构建/运行项目,并将此脚本放在项目根目录中:
#!/usr/bin/env bash
// 获取包含此脚本的目录的绝对路径
PROJECT_DIR=$(cd $(dirname $0) && pwd)
// 设置GOPATH,然后运行go build
GOPATH=${GOPATH}:${PROJECT_DIR} && cd ${PROJECT_DIR} && go build
即使您从不是项目根目录的目录中执行此脚本,它也应该正常工作。
英文:
I'm a Golang newb, but the best way to do this would probably be to create a shell script in each of your projects, to build/run your project, and put this script in your project root
#!/usr/bin/env bash
// get absolute path to the directory which contains this script
PROJECT_DIR=$(cd $(dirname $0) && pwd)
// set GOPATH as you wish, then run go build
GOPATH=${GOPATH}:${PROJECT_DIR} && cd ${PROJECT_DIR} && go build
this script should work, even if you execute it from a directory that is not the project root.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论