基于每个项目自动定义GOPATH

时间:2013-07-22 05:52:24

标签: bash go .bash-profile

对于我创建的每个项目,每次进入项目目录时我都必须export GOPATH={path_to_project}。必须有一个更简单的方法。是否有某种方法可以为给定目录创建.bashrc或.bash_profile文件来定义该项目的GOPATH?

例如,我有两个项目A和B.如果我在项目之间移动时没有重新定义的单个GOPATH,那么两个项目的二进制文件将存储在同一个地方。更重要的是,第三方库的二进制文件将存储在同一个地方,因此我无法按项目维护同一个库的多个版本。

但是,如果我能够在每个项目的基础上定义GOPATH,那么所有二进制文件和第三方库都依赖于项目。这似乎是在大多数其他语言环境中处理包管理的常用方法(ruby rbenv,python vertiualenv等)

8 个答案:

答案 0 :(得分:20)

(2018年第二季度: 请注意,对于vgo (now "module") project,最终可能会弃用GOPATH以支持基于项目的工作流。这样可以避免两年前我在下面提出的基于项目的GOPATH手册。

使用Go 1.11(2018年8月),GOPATH can be optional, with modules


对于Linux / Unix环境(基于Manage multiple GOPATH dirs with ease已经在上面的评论中提到),Herbert Fischer (hgfischer)the question表达了类似的想法:

  

只需在~/.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函数将设置{{1}当前环境到此目录。


2017年更新:如果您不想修改您的环境,您仍然可以在每个项目中使用一个GOPATH,方法是在Visual Studio Code中打开该项目的GOPATH文件夹({ {3}},这是一个多平台的IDE),与扩展" vscode"。

结合使用。

在该IDE中,您可以:

  • 将您的全局唯一src保留在名为GOPATH
  • 的设置中
  • 使用名为go.toolsGopath
  • 的设置推断您当前的GOPATH

Go for Visual Studio Code

这样,VSCode将在您的全球go.inferGopath中安装一系列工具(您也可以在VSCode外部使用)。
请参阅" vscode user settings":GOPATHgodepgolintguru,...

然而,您项目的godoc将是src的父文件夹:

Go tools that the Go extension depends on

从IDE编译/安装项目时,这是有效的 如果您想从命令行执行此操作,上面的原始答案仍然适用。

答案 1 :(得分:10)

您可以使用autoenv之类的工具来设置在cd进入特定目录时自动执行的脚本。

出于您的目的,示例/happy/go/path/yay/.env文件可能如下所示:

export GOPATH="/happy/go/path/yay"
export PATH="$GOPATH/bin:$PATH"

答案 2 :(得分:5)

我会写一个脚本,它可以从当前目录推断出正确的GOPATH,然后使用go命令别名来首先调用这个脚本。例如,一个非常简单的实现:

#!/bin/bash
# infer-gopath.sh

pwd

然后,在.bash_aliases中(或者你保留别名的地方):

alias go='GOPATH=$(infer-gopath.sh) go'

这会将GOPATH设置为仅用于调用infer-gopath.sh命令的go输出,因此它不会对您的shell产生任何持久影响。

答案 3 :(得分:3)

我的印象是go工具主动阻止“在每个项目的基础上维护同一个库的多个版本”,原因在于经验表明该策略不适用于大型代码库(例如作为谷歌的)。关于golang-nuts的包版本化已经进行了很多讨论:( search the list),似乎讨论仍然是开放的,正如Ian Lance Taylor在June 6, 2013 interview所指出的那样(搜索“版本化”这个词。)

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。)

答案 4 :(得分:2)

我知道这不是很聪明但我发现如果我只是去go项目的基本目录,我有src,pkg和bin文件夹,我只需输入:

export GOPATH=$(pwd)

这就好了!

答案 5 :(得分:1)

我无法发表评论,但要从@joshlf :::

中建立答案

别名go通过添加GOPATH - 我的方法不要求你处理/创建额外的文件:

alias go='GOPATH=$(echo $(pwd)) go'

欢呼声

答案 6 :(得分:0)

我喜欢the gopath() answer above的胆量,但我不喜欢(a)只为GOPATH命令设置go(我在vim插件中使用它,等),我也不喜欢(b)必须记住键入gopath而不是go:)

这是我最终添加到~/.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
    ))"
}

(我还在上面写了一些关于需求in this blog post

的额外讨论

答案 7 :(得分:0)

我是Golang的新手,但最好的方法可能是在每个项目中创建一个shell脚本,构建/运行你的项目,并将这个脚本放在你的项目根目录中:)

#!/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

此脚本应该可以工作,即使您从非项目根目录执行它。