If you’re a Golang user, chances are you’re going to have to manage and maintain versions of Golang. If you happen to be working on two different versions of Golang at the same time, you might want to use the Golang Version Management Tool to help you ease the burden without forcing you to skip versions.

This article will take a look at some of the tools I’ve been using in recent months, their strengths and weaknesses. I hope I can help students with similar needs.

Writing in the front

When developing new and old local projects in parallel, you will most likely encounter a vexing problem: how do you develop with two different versions of Golang Runtime?

In the current era of container and CI popularity, we seem to have been used to using Docker Run to switch between versions of various languages, to complete the development of different projects, and to test the compatibility of basic types of projects. With some tools that support remote debugging, the experience seems ok.

However, in terms of efficiency and complexity, it is always a bit higher than the local environment. So is there a more energy efficient and environmentally friendly way?

Golang-based version management tool: Voidint /g

After initially installing GVM, the tool didn’t feel “neat” enough, so I recompiled a version for my own use, tweaking some details based on github.com/voidint/g/.

If you don’t want to compile the installation yourself, you can install it the way the authors recommend:

curl -sSL https://raw.githubusercontent.com/voidint/g/master/install.sh | bash
Copy the code

If you are a user of oh-my-zsh, there are two ways to resolve the global g command conflict. The first way is to add unalias to the end of your.zshrc file:

echo "unalias g" >> ~/.zshrc # is optional. If another program (such as 'git') uses 'g' as an alias.
Remember to restart the shell, or reconfigure the source
Copy the code

Second, is to adjust ~ /. Oh – my – ZSH/plugins/git/git plugin. About the registration of g, in ZSH its annotations or deleted:

# alias g='git'
Copy the code

Complete configuration in my.zshrc:

# my g's bin directory has been adjusted to.gvm, so you may need some additional adjustments
export PATH="${HOME}/.gvm/bin:$PATH"
export GOROOT="${HOME}/.g/go"
export PATH="${HOME}/.g/go/bin:$PATH"
export G_MIRROR=https://gomirrors.org/
Copy the code

However, as I started using Golang, I found that I had some problems using both versions of Golang. Read the source code, see the installation defined in https://github.com/voidint/g/blob/master/cli/install.go:

	fmt.Println("Checksums matched")

	// Delete historical garbage files that may exist
	_ = os.RemoveAll(filepath.Join(versionsDir, "go"))

	Decompress the installation package
	iferr = archiver.Unarchive(filename, versionsDir); err ! =nil {
		return cli.NewExitError(errstring(err), 1)}// Rename the directory
	if err = os.Rename(filepath.Join(versionsDir, "go"), targetV); err ! =nil {
		return cli.NewExitError(errstring(err), 1)}// Re-establish the soft link
	_ = os.Remove(goroot)

	iferr := mkSymlink(targetV, goroot); err ! =nil {
		return cli.NewExitError(errstring(err), 1)
	}
	fmt.Printf("Now using go%s\n", v.Name)
	return nil
Copy the code

It is found that each version switch will re-establish the soft chain mapping. In the Issue area of the official project, there was a similar feedback: #44, the author gave a solution outside the program g.

So, if you’re looking for a simple tool that can quickly download the Golang Runtime precompiled from the web and doesn’t require multiple versions running at the same time, voidint/g will do the trick. If you need multiple versions running at the same time, So you can keep going.

Base-based version management tool: GVM

Because of the above problems, I began to consider the adjustment plan. First of all, consider switching back to github.com/moovweb/gvm. Speaking of GVM, those familiar with node.js ecology can easily associate NVM. Yes, their philosophy is the same, to write language management tools through Bash, which is language ecologically independent.

In Node.js, because the maintenance version download, update, delete, and switch functions are language independent (for example, the other tool is based on Node.js), it is actually more robust, and there is no problem with node.js configuration, language version management tool will not run, there is no problem with language version management. (Chicken-and-egg philosophy) But in Golang, precompiled binaries are actually language-neutral, and writing programs using Bash is a bit more verbose by comparison.

This is one of the reasons I didn’t stick with GVM in the first place. On top of that, GVM has a lot of users, but the authors have been inactive for a long time, so there are a lot of to-do items in the Issue and PR areas. There are also many errors or omissions in the official documentation.

But these are solvable.

There are three common problems with GVM users:

  • Failed to install the program. Procedure
  • The installation cannot continue after downloading the specified version of Golang failed
  • Does the user not know how to use the mirror resource

To solve the first problem, how to install GVM correctly, the official ReadMe installation will encounter problems in the ZSH environment, recommended to switch to the following installation:

curl -sSL https://github.com/moovweb/gvm/raw/master/binscripts/gvm-installer | bash
Copy the code

After executing, we should see the correct log output:

Cloning from https://github.com/moovweb/gvm.git to /home/ubuntu/.gvm No existing Go versions detected Installed GVM V1.0.22 Please restart your terminal session or to get started right away run 'source /home/ubuntu/.gvm/scripts/gvm`
Copy the code

Moving on to the second issue, when you first install a version of Golang, you may experience an “interruption” and get an incomplete package because we didn’t configure the download image address. The application will determine if we have already downloaded the application and will try to use the downloaded cached content first, regardless of whether it is complete or not. This will cause some users to repeatedly execute GVM install go1.17.3-b and find that everything is fine, but cannot complete the version download or switch.

It is also very simple to clear the cache:

Rm - rf ~ /. GVM/archive/go1.17.3. Darwin - amd64. Tar. Gz# or
rm -rf ~/.gvm/archive/
Copy the code

Then we’ll look at the third problem, how to use the image address to download and speed up the efficiency of switching Golang versions. In the official documentation, there is an introduction to its use:

Usage: gvm install [version] [options]
    -s,  --source=SOURCE      Install Go from specified source.Copy the code

However, this isn’t really what we’re looking for, because it addresses the online address of “specify Golang source”, not the address of the pre-built binary package, In https://github.com/moovweb/gvm/blob/master/scripts/install, we can see is a lot of default warehouse code, so if you want to build from scratch source, this parameter can help to you, But if you want to download binary, this parameter is useless.

. GO_SOURCE_URL=https://github.com/golang/gofor i in "$@"; do
		case $i in
			-s=*|--source=*)
				GO_SOURCE_URL=$(echo "$i" | sed 's/[-a-zA-Z0-9]*=//');; .Copy the code

Further down in the same file, we can see a function called download_binary() :

	# `GO_BINARY_BASE_URL` env allow user setting base URL for binaries
	# download, e.g. "https://dl.google.com/go".
	GO_BINARY_BASE_URL=${GO_BINARY_BASE_URL:-"https://storage.googleapis.com/golang"}
	GO_BINARY_URL="${GO_BINARY_BASE_URL}/${GO_BINARY_FILE}"
	GO_BINARY_PATH=${GVM_ROOT}/archive/${GO_BINARY_FILE}

	if [ ! -f $GO_BINARY_PATH ]; then
		curl -s -f -L $GO_BINARY_URL > ${GO_BINARY_PATH}

		if [[ $? -ne 0 ]]; then
			display_error "Failed to download binary go"
			rm -rf $GO_INSTALL_ROOT
			rm -f $GO_BINARY_PATH
			exit 1
		fi
	fi
Copy the code

There is a variable called GO_BINARY_BASE_URL, which we can adjust to do our job. Unfortunately, this parameter hasn’t been documented since it was incorporated in late 2019, and if you don’t read the code, you’ll probably never know that you can download resources from the image.

Here’s the configuration I’m currently using. After adding the following configuration to your SHELL’s RC, you should be able to quickly switch Golang using GVM as normal.

export GO111MODULE=on
export GOPROXY=https://goproxy.io,direct
# or
# exort GOPROXY="https://goproxy.cn"
export GOPATH="$HOME/go"
PATH="$GOPATH/bin:$PATH"


export GO_BINARY_BASE_URL=https://golang.google.cn/dl/
[[ -s "$HOME/.gvm/scripts/gvm"&&]]source "$HOME/.gvm/scripts/gvm"
export GOROOT_BOOTSTRAP=$GOROOT
Copy the code

Switching between versions of Golang is also easy, with just two commands:

GVM install go1.17.3 -b GVM use go1.17.3Copy the code

If you want to fully customize a Golang Base Docker image without using the official Golang team image, GVM is an easy choice compared to other tools, requiring no pre-build and no system selection.

From the official solution: Golang/DL

If you don’t like a three-way solution, you might want to try an official one. (That is, you don’t need to run multiple versions of Golang at the same time.)

Compared to the community scheme, the official one is more interesting: github.com/golang/dl. All updates from 1.5 to 1.17 have been officially maintained.

We can obtain the specific version of the installation tool by installing a common package, and “overwrite installation” :

Go get golang.org/dl/go1.17.3 go1.17.3 DownloadCopy the code

However, unlike the above, github.com/golang/dl/b… The write down logic in the user directory will make your installation directory in the user directory SDK folder, so if you use this method, the export path needs to be adjusted:

func goroot(version string) (string, error) {
	home, err := homedir()
	iferr ! =nil {
		return "", fmt.Errorf("failed to get home directory: %v", err)
	}
	return filepath.Join(home, "sdk", version), nil
}
Copy the code

other

In addition, there are two interesting projects, borrowed from Rustup :github.com/owenthereal… ; And from rbenv and Pyenv: github.com/syndbg/goen… .

The last

Recently, I have been taking notes to sort out the contents. I happened to see this draft of notes and sorted it out.

This article is written here, I hope to help you save some time, avoid small pits.

–EOF


We have a little group of hundreds of people who like to do things.

In the case of no advertisement, we will talk about software and hardware, HomeLab and programming problems together, and also share some information of technical salon irregularly in the group.

Like to toss small partners welcome to scan code to add friends. (To add friends, please note your real name, source and purpose, otherwise it will not be approved)

All this stuff about getting into groups


If you think the content is still practical, welcome to share it with your friends. Thank you.


This article is published under a SIGNATURE 4.0 International (CC BY 4.0) license. Signature 4.0 International (CC BY 4.0)

Author: Su Yang

Creation time: on December 15, 2021 statistical word count: 5707 words reading time: 12 minutes to read this article links: soulteary.com/2021/12/15/…