Go 1.8
With Go following a predetermined release schedule of February - August and a Release Candidate for Go 1.8 just a few days after this article, it looks like we should be able to talk about Go 1.8 without too much fear that things will change.
Lets start with some of the low-level changes.
You may remember that Go 1.7 introduced a new compiler backend that is based on SSA, or Static Single Assignment form, which helps improving code generation and allows for more optimizations to happen. At the time that backend was available only for the x86 amd64 platform. As of Go 1.8 however, this will be present for all the other platforms as well. And while for the x86-64 platform the performance increase was up to 10%, for all the other platforms it’s expected to be between 20% and 30%.
Not only the compiler backend has suffered changes. The compiler frontend has also been overhauled in order to allow further performance improvements.
Overall, Go 1.8 continues the work on getting back the compile speed lost in the 1.5 release and it’s now around 15% faster to compile than 1.7 but still slower than 1.4.
Speaking of compiler changes, you can now enjoy deploying Go to even more platforms than before with the addition of MIPS 32, both LE and BE, on platforms that support MIPS32r1 instruction set with FPU (either hardware or emulated by the kernel).
The Go tooling has also been updated with go fix
now converting the
golang.org/x/net/context
to context
in order to facilitate the migration
to the new context package. go vet
as also been updated so remember to run
it on your codebase in order to check for potential issues.
If you happen to encounter a bug in Go then you can use the new go bug
command which will help you pre-fill the bug report with all the system
information needed in order to ensure that the needed details are present.
There’s also a new supported build mode which enables Go applications to support compiling to and loading plugins. This will effectively allow new ways for applications to provide functionality based on the needs of their users. If you want to read more about it, you can see the documentation.
From 1.8, Go will not need an environment variable in order to determine the GOPATH. If this will not be present anymore, it will default to a the HOME/go as default directory but if you already have this set, then it will continue to work as before. You can see the commit which enables this here.
Go’s garbage collector did not go untouched in this release as well. As part of the ongoing effort to remove the stop-the-world stack rescanning, see the proposal document Go gained a new hybrid write barrier which should lower the garbage collection time pause to under 100us.
The function arguments will also no longer live until the end of the function, which means that memory can be freed before the function execution ends. For details about this functionality, you can read the issue and the implementation.
If you think that’s already a long list of changes, lets quickly see the various packages from the Go standard library and see what’s new or fixed for them. For the purpose of time, we’ll skip over 100 commits which are meant to enhance the performance across the board.
Go 1.8 brings a much more mature TLS stack to crypto/tls
, benefiting HTTPS
clients and servers.
Support for ChaCha20-Poly1305 based cipher suites, and the X25519 key exchange bring speed and security improvements.
If you were setting tls.Config.CurvePreferences
you will want to add tls.X25519
, and if you were setting tls.Config.CipherSuites add:
1 2 |
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, |
If CipherSuites
is nil, ChaCha or AES will be preferred automatically based on hardware support availability.
Maturity is not just features, but flexibility as well. 1.8 introduces a few callbacks like the existing GetCertificate that allow a lot of custom extensions.
GetConfigForClient is
run for every server connection, and allows customizing all fields of the
Config
based on the information in the ClientHelloInfo,
which has been expanded. This allows all kinds of things, like enabling client
certificates (#15707) or HTTP/2 selectively based on the website being requested:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
type getConfigForClient func(*tls.ClientHelloInfo) (*tls.Config, error) func partialHTTP2Config(baseConfig *tls.Config, http2Sites []string) getConfigForClient { http2Config := baseConfig.Clone() // new in 1.8, too http2Config.NextProtos = []string{"h2", "http/1.1"} http1Config := baseConfig.Clone() http1Config.NextProtos = []string{"http/1.1"} return func(chi *tls.ClientHelloInfo) (*tls.Config, error) { for _, enabled := range http2Sites { if chi.ServerName == enabled || strings.HasSuffix(chi.ServerName, "."+enabled) { return http2Config, nil } } return http1Config, nil } } |
The new Conn
field in ClientHelloInfo
allows GetConfigForClient
or
GetCertificate
to make decisions based on the remote or local IP (needed for
clients that don’t support SNI), but shouldn’t be used to write or read data as
that would corrupt the handshake.
GetClientCertificate lets clients pick their certificate based on the server CA preferences.
Finally, VerifyPeerCertificate enables custom certificate checking logic, which I hope will be implemented by external libraries to provide for example revocation and CT checks.
The Go TLS stack also learned to write debugging key files to a KeyLogWriter file. These files can be loaded into Wireshark to decrypt the TLS traffic.
Interestingly, a comment by Adam Langley in the crypto/tls
source
had predicted the Lucky13 vulnerability in CBC cipher suites. It has since been
fixed in OpenSSL, but full countermeasures are extremely complex, so they
haven’t been ported to the Go library since better cipher suites are available.
1.8 introduces partial mitigation, which make the attack harder.
Here’s the full changelog with some other minor improvements.
database/sql
was already covered in a previous article by Daniel Theophanes.
encoding
package has a few changes:
encoding/binary
: supports bool valuesencoding/json
: adds struct and field name to UnmarshalTypeError message with this changeencoding/json
: uses standard ES6 formatting for numbers during marshal, with this changeencoding/xml
: wildcard support for collecting all attributes, with this change
expvar
gained a way to retrieve the value back using the new Value method,
and it also exports the the handler thus allowing
usage via different ServeMux.
net
has some interesting changes as well:
- adds Buffers type and writev on Unix and Windows
- adds Resolver type, Dialer.Resolver, and DefaultResolver
- will break up >1GB reads and writes on stream connections, with this change
- will respect resolv.conf rotate option, with this change
- use libresolv rules for ndots range and validation, with this change
net/http
, one of the most popular packages in Go, was also very popular with
a lot of contributions to it. Below you can find a selection of them:
- the Server gained Server.Close & Server.Shutdown for forced & graceful shutdown
- add Server.ReadHeaderTimeout, IdleTimeout, document WriteTimeout, with this commit
- adds Transport.ProxyConnectHeader to control headers to proxies, with this commit
- HTTP/2 server push is now supported
- make Server Handler’s Request.Context be done on conn errors, with this commit
- make Server log on bad requests from clients, with this commit
- make Transport support international domain names, with this commit
- support If-Match in ServeContent, with this commit
The runtime
also gained additional features like:
- profile goroutines holding contended mutexes, with this commit
- disable stack rescanning by default, with this commit
- include pre-panic/throw logs in core dumps, with this commit
sort
gained new helpers for sorting slices, with this commit.
As such, sorting slices is a lot simpler now and you can see an example bellow
for the new way to do it:
1 2 3 4 5 6 |
sort.Slice(s, func(i, j int) bool { if s[i].Foo != s[j].Foo { return s[i].Foo < s[j].Foo } return s[i].Bar < s[j].Bar }) |
The testing
package gained new functionality, among which:
- add Name method to *T and *B, with this commit
- tests and benchmarks failed if a race occurs during execution will be marked as such, with this commit
- benchtime is now respected on very fast benchmarks, with this commit
The overall documentation of the Go standard library has received a lot of contributions. As always, if you think something can be improved, please open up issues in order to at least let others know where the problems are or even give it a try contribute to it.
If you are eager to try Go 1.8, you can either do it so now, and use the Go 1.8 Beta 2 release or you can wait a few more days for the Release Candidate 1, and you are highly encouraged to do so in order to guarantee a smooth release of 1.8 and enjoy it in production without any problems.
To view the full list of changes, you can read this the Draft Release Notes.
Finally, if you want to stay up to date with the developments of Go, you are encouraged to follow the @golang_cls Twitter account which will provide a list of curated commits as they are added to Go.