by Ridham Tarpara
All you need to know about Go version 1.11
Go 1.11 hit the ground on 24 August 2018. It introduces a few really needed tools and components such as versioned modules, WebAssembly support, and debugging improvements. It also brings some changes to core packages and performance/run-time.
As always, the release maintains the Go 1 promise of compatibility. So almost all Go programs continue to compile and run as before with this update. There are no changes to the language specification.
Let’s take a look at what’s new.
Modules
Go 1.11 includes experimental support for Go modules, including a new module-aware go get
command.
The quickest way to take advantage of the new module support is to check out your repository into a directory outside, create a go.mod file and run Go commands from within that file tree.
Let’s demo this. I am using the testify-powerful and standard Go testing libraries.
Let’s clone the testify repo in my favorite folder ~/proj/github
.
$ git clone https://github.com/stretchr/testify ~/proj/github/testify$ cd ~/proj/github/testify
Now, to use Go commands from here, you need to initialize this repo as a module with the following command:
go mod init github.com/stretchr/testify
Where github.com/stretchr/testify
is the location you would generally put this repo, under the Go src folder.
This command will create a go.mod file in the root of the folder. In a project already using an existing dependency management tool like godep, glide, or dep, go mod init
will also add require statements matching the existing configuration.
Now if you open the go.mod
file, you can see the list of dependencies with the module name.
$ vi go.mod
module github.com/stretchr/testify
require ( github.com/davecgh/go-spew v1.1.0 github.com/pmezard/go-difflib v1.0.0 github.com/stretchr/objx v0.1.0)
As you’ll notice, these three are the dependencies of the testify. This is testify’s Gopkg.toml
file:
[prune] unused-packages = true non-go = true go-tests = true
[[constraint]] name = “github.com/davecgh/go-spew” version = “~1.1.0”
[[constraint]] name = “github.com/pmezard/go-difflib” version = “~1.0.0”
[[constraint]] name = “github.com/stretchr/objx” version = “~0.1.0”
Now that the module has been initialized, you can use any Go command from this folder.
╭─ ~/proj/github/testify ‹master*› ╰─$ go build go: finding github.com/davecgh/go-spew v1.1.0go: finding github.com/pmezard/go-difflib v1.0.0go: finding github.com/stretchr/objx v0.1.0go: downloading github.com/davecgh/go-spew v1.1.0go: downloading github.com/pmezard/go-difflib v1.0.0go: downloading github.com/stretchr/objx v0.1.0
╭─ ~/proj/github/testify ‹master*› ╰─$ go test PASSok github.com/stretchr/testify 0.001s
So with Go 1.11 and modules, you can write your Go modules anywhere you like and you don’t need to maintain a copy in a specific sub directory of your $GOPATH
.
WebAssembly
Go 1.11 adds an experimental port to WebAssembly.
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
Now we can run Go in the browser, and vice versa — we can run JavaScript in Go easily. Although this feature is in the experimental state, it’s still pretty useful.
This small example calls Go from the Web:
wasm-exec.html
<!doctype html><!--Copyright 2018 The Go Authors. All rights reserved.Use of this source code is governed by a BSD-stylelicense that can be found in the LICENSE file.--><html>
<head> <meta charset="utf-8"> <title>Go wasm</title></head>
<body> <script src="wasm_exec.js"></script> <script> if (!WebAssembly.instantiateStreaming) { // polyfill WebAssembly.instantiateStreaming = async (resp, importObject) => { const source = await (await resp).arrayBuffer(); return await WebAssembly.instantiate(source, importObject); }; } const go = new Go(); let mod, inst; WebAssembly.instantiateStreaming(fetch("test.wasm"), go.importObject).then((result) => { mod = result.module; inst = result.instance; document.getElementById("runButton").disabled = false; }); let printMessage // Our reference to the Go callback let printMessageReceived // Our promise let resolvePrintMessageReceived // Our promise resolver function setPrintMessage(callback) { printMessage = callback resolvePrintMessageReceived() } async function run() { console.clear() // Create the Promise and store its resolve function printMessageReceived = new Promise(resolve => { resolvePrintMessageReceived = resolve }) const run = go.run(inst) // Start the wasm binary await printMessageReceived // Wait for the callback reception printMessage('Hello Wasm!') // Invoke the callback await run // Wait for the binary to terminate inst = await WebAssembly.instantiate(mod, go.importObject) // reset instance } </script>
<button onClick="run();" id="runButton" disabled>Run</button></body>
</html>
go-call.go
package main
import ( "fmt" "syscall/js")
var done = make(chan struct{})
func main() { callback := js.NewCallback(printMessage) defer callback.Release() // To defer the callback releasing is a good practice setPrintMessage := js.Global().Get("setPrintMessage") setPrintMessage.Invoke(callback) <-done}
func printMessage(args []js.Value) { message := args[0].String() fmt.Println(message) done <- struct{}{} // Notify printMessage has been called}
You can find more examples here. And here is a video on building a calculator with WebAssembly.
Other changes to consider
- Because Go module support assigns special meaning to the
@
symbol in command line operations, thego
command now disallows the use of import paths containing@
symbols. - With the new
runtime/trace
package's user annotation API, users can record application-level information in execution traces and create groups of related goroutines. Thego
tool
trace
command visualizes this information in the trace view and the new user task/region analysis page. - The runtime now uses a sparse heap layout so there is no longer a limit to the size of the Go heap (previously, the limit was 512GiB). This also fixes rare “address space conflict” failures in mixed Go/C binaries or binaries compiled with
-race
. - time: Parsing of timezones denoted by sign and offset is now supported. In previous versions, numeric timezone names (such as
+03
) were not considered valid, and only three-letter abbreviations (such asMST
) were accepted when expecting a timezone name. - text/scanner: The
Scanner.Scan
method now returns theRawString
token instead ofString
for raw string literals. - There are changes in crypto, encoding, net/http, os, runtime, sync, mime and few others which you can read about here.
If you enjoyed this article, spare me some claps — it means the world to the writer. Follow me if you want to read more articles about Go, JavaScript, Technology, and Startups.