34

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

例如,我有两个 go 项目 A 和 B。如果我有一个在项目之间移动时未重新定义的单一 GOPATH,那么两个项目的二进制文件将存储在同一个位置。更重要的是,第三方库的二进制文件将存储在同一个地方,所以我无法在每个项目的基础上维护同一个库的多个版本。

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

4

8 回答 8

24

(2018 年第二季度:请注意,对于vgo(现在的“模块”)项目GOPATH可能最终会被弃用,而支持基于项目的工作流程。这将避免GOPATH两年前我在下面提出的基于手动项目的手动)

对于 Go 1.11(2018 年 8 月),GOPATH可以是可选的,带有 modules


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

~/.bashrc只需在您的(或~/.bash_profile)中包含以下代码段,然后使用source ~/.bashrc.
此代码段将创建一个 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 年更新:如果您不想修改您的环境,您仍然可以在GOPATH每个项目中使用一个,src方法是在 Visual Studio Code(vscode,它是一个多平台 IDE)中打开该项目的文件夹,并结合扩展名“去 Visual Studio 代码“。

在该 IDE 中,您可以:

  • GOPATH在名为go.toolsGopath.
  • GOPATH使用名为的设置推断您的电流go.inferGopath

vscode 用户设置

这样,VSCode 将在您的全局中安装一组工具GOPATH(供您在 VSCode 外部使用)。
请参阅“ Go 扩展依赖的 Go 工具”: godep, golint, guru, godoc, ...

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

本地 GOPATH

当您从 IDE 编译/安装项目时,它会起作用。
如果您想从命令行执行此操作,则上面的原始答案仍然适用。

于 2015-02-08T13:44:26.013 回答
10

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

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

export GOPATH="/happy/go/path/yay"
export PATH="$GOPATH/bin:$PATH"
于 2013-07-24T00:37:22.760 回答
5

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

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

pwd

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

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

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

于 2013-07-22T06:30:39.527 回答
5

我知道这不是很聪明,但我发现如果我只是转到 go 项目的基本目录,其中有 src、pkg 和 bin 文件夹,我可以简单地键入:

export GOPATH=$(pwd)

这一切都很好!

于 2018-02-17T17:24:02.437 回答
3

我的印象是该go工具不鼓励“在每个项目的基础上维护同一个库的多个版本”,因为经验表明该策略不适用于大型代码库(例如 Google 的)。关于 golang-nuts 上的包版本控制已经有相当多的讨论:(搜索列表),并且似乎讨论仍然是开放的,正如 Ian Lance Taylor 在2013 年 6 月 6 日的采访中指出的那样(搜索单词“版本控制”)。

go打包系统旨在让每个项目都有自己的目录结构;唯一的限制是它们都必须是GOPATH. 这样做的好处是它可以与版本控制系统很好地交互,只要 VCS 主机始终构建。在上面提到的博客采访中,ILT 建议:

我们在内部做的是对导入的代码进行快照,并不时更新该快照。这样,如果 API 发生变化,我们的代码库就不会意外中断。

用“我的其他库”代替“导入的代码”,这似乎是一种可能;你可以有两个go目录,生产和开发;对于开发,您可以将开发目录放在路径中的第一位,这样开发二进制文件和库就不会污染生产目录。我不知道这是否足够。

如果您真的想GOPATH为每个项目单独设置一个,我建议您执行以下操作:

1)使每个项目的GOPATH结束在一个名为go(或类似)的目录

2)推断GOPATH使用类似以下shell函数的东西(几乎完全未经测试):

gopath() {
  GOPATH="$(
    ( while [[ $PWD != / && $(basename $PWD) != go ]]; do
        cd ..
      done
      if [[ $PWD == / ]]; then
        echo $GOPATH
      else
        echo $PWD
      fi
    ))" go "$@"
}

然后,只要您当前的工作目录位于项目存储库中的某个位置,您就可以使用gopath而不是。go(更复杂的可能性可能包括使用明确提供的项目路径(如果有的话)来推断GOPATH。)

于 2013-07-22T18:44:22.377 回答
1

我无法发表评论,但要建立来自@joshlf ::: 的答案

go通过在前面加上GOPATH-- 我的方法不需要你处理/创建一个额外的文件来别名:

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

干杯

于 2016-04-08T20:44:48.097 回答
0

我喜欢上面 gopath() 答案的胆量,但我不喜欢 (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
    ))"
}

(我还在这篇博文中写了上面的内容,并对需求进行了一些额外的讨论)

于 2014-07-21T00:56:50.707 回答
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

这个脚本应该可以工作,即使你从一个不是项目根目录的目录中执行它。

于 2017-01-18T03:33:20.593 回答