Simple Go multi-version management mechanism

A programming language full of vitality must be constantly evolving. As the Go project continues to develop, there will be many iterations of smaller versions within each major version. For Go version updates, how do we manage multiple versions?


The importance of multi-version management


Here are just a few reasons why we need multi-version management in Go.


Stability considerations: While Go1 has been following the backward compatibility guidelines well, we generally do not upgrade directly to the latest version for stability reasons.

Multi-project development: The Go versions that each project depends on are inconsistent.

Version Compatibility: Test the code for forwarding and backward compatibility, or ensure the correctness of bug fixes in different Go versions. For open-source projects, ensuring version compatibility is very important.


How to manage multiple versions?


We need to have two prerequisites


A version of Go is already installed. git is installed.


Install


Running the go install golang.org/dl/go<version> command will download a wrapper for the specific Go version.

$ go install golang.org/dl/go < version > @latest _

Through the wrapper, download a specific Go version and its corresponding toolchain.

$ go <version>  download

For example, to install version 1.14.12, you can do this.

 $ go install golang.org/dl/go1.14.12@latest 
$ go1.14.12 download _ _ _ _ _ _

Use


Using the wrapper go1.14.12, we can build and test against Go v1.14.12.

$ go1.14.12 mod init  hello
go :  creating  new  go . mod : module  hello 
$ echo  'package main; import "fmt"; func main() { fmt.Println ("Hello, World") }'   hello .go
$ go1.14.12  build _
$  ./ hello
 Hello , World 

Of course, if you want to make Go v1.14.12 "clunky" and become the go-command spokesperson, you can do so.

$ go version
go version go1.17  darwin / 64 
$  export GOROOT = $ (  go1.14.12  env GOROOT ) 
$  export  PATH = $ { GOROOT } / bin : $ PATH
$ go version
go version go1 .14.12  darwin / 64

This go1.14.12 env GOROOT path is what the Go v1.14.12 version is about. Therefore, if we want to uninstall this version, we can directly delete the path folder; if we want to read the source code of this version, we can directly view the content of src / under the path.


Get the latest development version


There is a special version marker: gotip, which is used to install the latest development version.

$ go install golang.org/dl/gotip@latest _ _ _
$ gotip download

As you can see, the latest development version currently pulled is go1.18-1afa432.

Realize ideas


The secret to implementing multi-version download and installation lies in the repository https://go.googlesource.com/dl, and https://github.com/golang/dl is its mirror repository.


Looking at the repository code, we can see a series of version directories

Choose a version at will to enter, you will find that there is a main.go file

The main.go file content is as follows

The go1.14.12 wrapper we downloaded via go install golang.org/dl/go1.14.12@latest is compiled from this main.go.


Therefore, our subsequent download and run logic through the go1.14.12 wrapper lies in the Run method in the internal / version package.

// Run runs the "go" tool of the provided Go version. 
func  Run ( version  string ) { 
 log . SetFlags ( 0 ) // Get the Go installation directory 
 root ,  err  :=  goroot ( version ) if  err  != nil { 
  log.Fatalf ( "% s : %v" ,  version ,  err ) }  
  
  // Logical when executing go<version> download command if  len ( os . Args ) == 2 &&  os . Args [ 1 ] == "download" { if  err  :=  install ( root ,  version );  err  != nil { 
   log . Fatalf ( "%s: download failed: %v" ,  version ,  err ) } 
  os . Exit ( 0 ) } 
  
  // Determine the Go installation status of this version if  _ ,  err  :=  os . Stat ( filepath . Join ( root ,  unpackedOkay ));  err  != nil { 
  log . Fatalf ( "%s: not downloaded. Run '%s download' to install to %v" ,  version ,  version ,  root ) } // run this version Go 
 runGo ( root ) }

For reasons of space, the downloaded install and runGo function logic will not be expanded in this article. Students who want to know more can explore it by themselves.


In addition, in order to have a Go wrapper main program for each version (to avoid repeated manual operations), a help command genv is used here: The wrapper code for the corresponding version can be quickly generated <version>/main.go. See the internal/genv/main.go code for the implementation here.


This article introduces the multi-version management solution officially provided by Go, including use, installation, uninstallation, etc., you can feel its simplicity and efficiency. At the same time, we briefly reviewed this set of implementation code logic.

1 view0 comments

Recent Posts

See All