goenv: go get binaries: command not found

Okay so, I’m new to Go, and found goenv since I’m familiar with rbenv, pyenv, etc. I’m having trouble getting stuff installed with go get commands that have binaries to actually ever say anything other than “command not found”.

Forgive me if this has already been discussed, I did browse the closed issues and the open issues but couldn’t find exactly this.

I’m assuming this works a lot like rbenv, etc.

I use goenv as I would any other. goenv install 1.8.3 goenv global 1.8.3

I install dependencies such as revel and dep with: go get -u github.com/golang/dep/cmd/dep go get github.com/revel/revel

goenv rehash and I still am getting: -bash: dep: command not found -bash: revel: command not found

In my ~/.bash_profile on MacOS Sierra:

export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
export GOPATH="$HOME/go"

As seen above, I even tried something from another closed issue for setting GOPATH= to ~/go as default. But no dice.

Any tips on this?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 3
  • Comments: 21 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Once I added these lines, it seems to have helped.

export GOPATH="$HOME/go"
export PATH="$PATH:$GOPATH/bin"

But I’m not sure that should be required if goenv works and manages these things but I’ll roll with it for now.

@joshuairl (or anyone else who has the same issue), try the following:

goenv global 1.9.4
goenv rehash

now run go env to check if your env is set up properly.

Isn’t the usual method of these *env tools to write a shim when installing a new package, shim that will itself run the right version of the package’s binary/script?

goenv install VERSION
goenv global VERSION

# installs PACKAGE in VERSION,
# add shim in $GOENV_ROOT/shims, which is in PATH thanks to goenv init
go get -u PACKAGE

# now the shim is available

Then, when executed, the shim searches for the actual binary and execute it. It may also check what is the current version, if the real executable is available for this version, or other logic things, and display useful messages.

I currently have to do the following to make it partially work:

# I installed goenv with basher
export GOENV_ROOT="${BASHER_PACKAGES_PATH}/syndbg/goenv"
eval "$(goenv init -)"
export PATH=${GOPATH}/bin:${PATH}

…but now my PATH is fixed to the first global version I defined. If I change the global order, of I have a different local version defined, my PATH won’t be updated and the executables won’t be found. I’ll have to manually update my PATH each time I change version.

@syndbg I tried it, but I still don’t understand. I have the following in my .bash_profile:

export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
export PATH="$GOROOT/bin:$PATH"
export PATH="$GOPATH/bin:$PATH"

And indeed, if I install a tool, e.g. gb I can now use it from the command line. This part is ok.

However, I noticed that now the version of go which is used always sticks to the path set in ~/.goenv/version.

Consider the following:

I’m in $HOME:

$ goenv versions
  system
* 1.11.2 (set by /home/attilio/.goenv/version)
  1.12.1
$ which go
/home/attilio/.goenv/versions/1.11.2/bin/go

–> OK

However, say I’m in a project using 1.12.1:

$ goenv versions
  system
  1.11.2
* 1.12.1 (set by /home/attilio/p/test/.go-version)
$ which go
/home/attilio/.goenv/versions/1.11.2/bin/go

–> NOK

I think dynamically changing the $PATH is not the best solution either. Can’t we have the extra binaries somehow installed into ~/.goenv/shims instead? And then get rid of these two lines:

export PATH="$GOROOT/bin:$PATH"
export PATH="$GOPATH/bin:$PATH"

And still have correct go and binaries versions.

@kadaan Thanks, Your solution works for me.

And, my environment configuration.

export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"

if command -v goenv 1>/dev/null 2>&1; then
    eval "$(goenv init -)"
fi

@syndbg @pawamoy @attil-io @DuncanHills Why can’t we have the shims support binaries that get created by go get calls?

I was able to get this to work locally by changing go-rehash.list_executable_names to:

# List basenames of executables for every Go version
list_executable_names() {
  local version file
  goenv-versions --bare --skip-aliases | \
  while read version; do
    for file in "${GOENV_ROOT}/versions/${version}/bin/"*; do
      echo "${file##*/}"
    done
    # ---  New Lines
    if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then
      local gopath="${HOME}/go/${version}"
      if [ -n "${GOENV_GOPATH_PREFIX}" ]; then
        gopath="${GOENV_GOPATH_PREFIX}/${version}"
      fi
      for file in "${gopath}/bin/"*; do
        echo "${file##*/}"
      done
    fi
    # --- New Lines
  done
}

And goenv-whence.whence to:

whence() {
  local command="$1"
  goenv-versions --bare | while read version; do
    path="$(goenv-prefix "$version")/bin/${command}"
    if [ ! -x "$path" ]; then
      # --- New Lines
      if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then
        local gopath="${HOME}/go/${version}"
        if [ -n "${GOENV_GOPATH_PREFIX}" ]; then
          gopath="${GOENV_GOPATH_PREFIX}/${version}"
        fi
        path="${gopath}/bin/${command}"
        if [ ! -x "$path" ]; then
          continue
        fi
      else
      # --- New Lines
        continue
      fi
    fi

    [ "$print_paths" ] && echo "$path" || echo "$version"
  done
}

And lastly, goenv-which to:

for version in "${versions[@]}"; do
  if [ "$version" = "system" ]; then
    PATH="$(remove_from_path "${GOENV_ROOT}/shims")"
    GOENV_COMMAND_PATH="$(command -v "$GOENV_COMMAND" || true)"
  else
    GOENV_COMMAND_PATH="${GOENV_ROOT}/versions/${version}/bin/${GOENV_COMMAND}"
  fi
  if [ -x "$GOENV_COMMAND_PATH" ]; then
    break
  # --- New Lines
  elif [[ "$version" != "system" && "${GOENV_DISABLE_GOPATH}" != "1" ]]; then
    if [ -n "${GOENV_GOPATH_PREFIX}" ]; then
      GOENV_COMMAND_PATH="${GOENV_GOPATH_PREFIX}/${version}/bin/${GOENV_COMMAND}"
    else
      GOENV_COMMAND_PATH="${HOME}/go/${version}/bin/${GOENV_COMMAND}"
    fi
    if [ -x "$GOENV_COMMAND_PATH" ]; then
      break
    fi
  # --- New Lines
  fi
done

Once that is done, my shim path contains shims for binaries that got create by running go get ...:

❯ ls -al ~/.zplugin/plugins/syndbg---goenv/shims
.rwxr-xr-x 458 myuser  1 Dec 20:26 go*
.rwxr-xr-x 458 myuser  1 Dec 20:26 godoc*
.rwxr-xr-x 458 myuser  1 Dec 20:26 gofmt*
.rwxr-xr-x 458 myuser  1 Dec 21:17 gox*
.rwxr-xr-x 458 myuser  1 Dec 21:17 smartthings_exporter*

And then goenv which works:

❯ goenv which gox                                                                                                                                                                                                                  
/Users/myuser/Source/golang/1.11.3/bin/gox

And goenv whence works as well:

❯ goenv whence gox                                                                                                                                                                                                                 
1.11.3

Lastly, running the shimmed command works as well:

~/Source/golang/1.11.3/src/git..com/.../myapp ····························································GO v1.11.3
❯ gox --version
flag provided but not defined: -version
Usage: gox [options] [packages]
...
❯

But if I’m in a different folder and the go version doesn’t have gox, then I get the correct response:

~/Source ···········································································
❯ gox
goenv: 'gox' command not found

The 'gox' command exists in these Go versions:
  1.11.3

Finally, add the goenv-goget-plugin to goenv and it will automatically rehash when go get commands complete.

Bump, I don’t really get the usefulness of this command if it doesn’t segregate the binary installation directory as well. The user can easily add a global go bin directory to their path but goenv should install and hash commands from the current go directory’s bin path.

@syndbg Same here.

Environment

$ cd ~/.goenv
$ git log --pretty=format:"%C(blue)%ad %C(yellow)%h %C(red)%d %C(reset)%s %C(green)[%an]" --topo-order --date=short -1
2017-10-26 e7ed8e5 (HEAD -> master, tag: 1.7.0, origin/master, origin/HEAD) Merge pull request #35 from kteru/feature/1.9.2_1.8.5 [Anton Antonov]

$ env | grep go
GOENV_ROOT=/Users/myth/.goenv
PATH=/usr/local/sbin:/Users/myth/.goenv/shims:/Users/myth/.goenv/bin:/usr/local/opt/php70/bin:/Users/myth/.nodenv/shims:/Users/myth/.composer/vendor/bin:/Users/myth/.local/bin:/Users/myth/.rbenv/shims:/Users/myth/.pyenv/shims:/Users/myth/.dotfiles/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/X11/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Library/TeX/texbin:/Applications/Wireshark.app/Contents/MacOS

$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/myth/go"
GORACE=""
GOROOT="/Users/myth/.goenv/versions/1.9.0"
GOTOOLDIR="/Users/myth/.goenv/versions/1.9.0/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/vq/k0y6n92j6r5dk_hx_jrl62jh0000gn/T/go-build228413040=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

Reproduce steps

$ vi ~/.goenv/libexec/goenv-which
  41 for version in "${versions[@]}"; do
  42   if [ "$version" = "system" ]; then
  43     PATH="$(remove_from_path "${GOENV_ROOT}/shims")"
  44     GOENV_COMMAND_PATH="$(command -v "$GOENV_COMMAND" || true)"
++45     >&2 echo "PATH(gover: system): $PATH"
++46     >&2 echo "GOENV_COMMAND_PATH: $GOENV_COMMAND_PATH"
  47   else
  48     GOENV_COMMAND_PATH="${GOENV_ROOT}/versions/${version}/bin/${GOENV_COMMAND}"
++49     >&2 echo "PATH(gover: $version): $PATH"
++50     >&2 echo "GOENV_COMMAND_PATH: $GOENV_COMMAND_PATH"
  51   fi
  52   if [ -x "$GOENV_COMMAND_PATH" ]; then
  53     break
  54   fi
  55 done

$ mv ~/go{,.bak}

$ go get -u github.com/nsf/gocode
PATH(gover: 1.9.0): /Users/myth/.goenv/libexec:/Users/myth/.goenv/plugins/go-build/bin:/usr/local/sbin:/Users/myth/.goenv/shims:/Users/myth/.goenv/bin:/usr/local/opt/php70/bin:/Users/myth/.nodenv/shims:/Users/myth/.composer/vendor/bin:/Users/myth/.local/bin:/Users/myth/.rbenv/shims:/Users/myth/.pyenv/shims:/Users/myth/.dotfiles/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/X11/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Library/TeX/texbin:/Applications/Wireshark.app/Contents/MacOS:/Users/myth/go/bin
GOENV_COMMAND_PATH: /Users/myth/.goenv/versions/1.9.0/bin/go

$ goenv which gocode
PATH(gover: 1.9.0): /Users/myth/.goenv/libexec:/Users/myth/.goenv/plugins/go-build/bin:/usr/local/sbin:/Users/myth/.goenv/shims:/Users/myth/.goenv/bin:/usr/local/opt/php70/bin:/Users/myth/.nodenv/shims:/Users/myth/.composer/vendor/bin:/Users/myth/.local/bin:/Users/myth/.rbenv/shims:/Users/myth/.pyenv/shims:/Users/myth/.dotfiles/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/X11/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Library/TeX/texbin:/Applications/Wireshark.app/Contents/MacOS:/Users/myth/go/bin
GOENV_COMMAND_PATH: /Users/myth/.goenv/versions/1.9.0/bin/gocode
goenv: gocode: command not found

$ which ~/go/bin/gocode
/Users/myth/go/bin/gocode

Expected behavior

Can locate program file.

Actual behavior

Cannot locate program file.