Our 16th Meetup at the 16th of February with a quick tour on Go 1.16 😊 . We will also have an outlook on the Go generics proposal.
Go 1.16 is expected to be released this Februrary! 🎉 🎆
From the preliminary release notes
⚠️ io/ioutil
gets deprecated- package remains and will continue to work like before but new code should use functions from
io
andos
instead ioutil
functions will become wrappers aroundio
andos
, exampleioutil.ReadFile
- package remains and will continue to work like before but new code should use functions from
⚠️ 32-bit iOS and macOS support is dropped- 🎉 Go adds support for the 64-bit macOS ARM architecture (aka Apple Silicon) with
GOOS=darwin, GOARCH=arm64
crypto will be slower on this architecture since the optimized assembly code is still missingThere are arm64 assembly implementations: https://tip.golang.org/src/crypto/aes/cipher_asm.go and https://tip.golang.org/src/crypto/aes/asm_arm64.s
⚠️ GO111MODULE=on
is now the default, i.e. go tools work in go modules mode by defaultgo build
andgo test
do not modify yourgo.mod, go.sum
anymore- those two commands report if an module or checksum needs to be added or updated
- use
go get
orgo mod tidy
to do tha
- 🎉
runtime/metrics
is a new package that provides a stable interface for accessing runtime metrics- generalizes
runtime.ReadMemStats
and others
- generalizes
GODEBUG=inittrace=1
prints execution time and memory allocation for allinit
calls, e.g. to analyze startup time regressions- See State of Go @ FOSDEM 2021 for another overview of the additions and changes coming with this release
- 🏎️ the linker is faster, requires less memory and binaries are getting smaller as a result of more aggressive symbol pruning¹
- ¹ my naïve explanation of symbol pruning:
- a symbol contains metadata about the addresses of its variables and functions (source)
- 💡 you can show the symbols (symbol-table) of a binary using
nm <binary-file>
(runningstrip <binary-file>
will remove them all) - symbol pruning refers to the removal of symbols that are unused, e.g. uncalled functions from imported libraries
- initial pull request and go command support
- embed.go is only 423 lines including comments and blank lines
- strings are stored in plain-text in the binary
- embedded files must be located inside the package (that imports
embed
) directory or its subdirectories - you can embed files as
string
,[]byte
orembed.FS
- use
embed.FS
when importing multiple (a tree of) files into a variable
- use
- using the embed directive requires to import
embed
even when usingstring
or[]byte
variables (use blank import `import _ "embed") // go:embed pattern [pattern...]
where paths usepath.Match
patternsstring
and[]byte
can only have a single pattern
- file patterns can be quoted like strings to embed paths containing spaces
- directories are embedded recursively while paths beginning with _ or . are excluded
- note that
// go:embed dir/*
will embeddir/.foo
but// go:embed dir
will not!
- note that
- patterns must not begin with ., .. or /
- invalid patters and matches (e.g. a symbolic link) will cause the compilation to fail
- embed directive can only be used with exported or unexported global variables at package scope
- run example:
source .env && go run ./cmd/embed :12345
- calling
strings
on the binary shows that content is embedded as plain-text
- with
os.ReadDir
/fs.ReadDir
we get to new functions for listing directory contents- those functions are a lot more efficient than
ioutil.ReadDir
because they do not require to callstat
for each directory entry - for details see Ben Hoyts' article
- fun fact, those functions are inspired by Python's
os.scandir
- to get the performance benefit of
ReadDir
when walking directory trees you need to usefilepath.WalkDir
instead offilepath.Walk
,filepath.WalkDir
passesfs.DirEntry
instead ofos.FileInfo
into theWalkFn
- those functions are a lot more efficient than
type FS interface {
Open(name string) (File, error)
}
io.FS
filesystem abstraction interface- prior art is
afero
but it has a much larger interface (and functionality, e.g. supports writes) embed.FS
implements this so you can easily work with embedded directory trees- pretty useful for tests, e.g. to prevent side effects →
testing/fstest.MapFS
is an in-memory file system - accept
fs.FS
and make your API filesystem agnostic, i.e. work transparently with a local directory, s3 block storage, remote file system etc. - 💡 you can easily test your custom file systems by passing them into
fstest.TestFS
- prior art is
type DeleteFS interface {
FS
Delete(name string) error
}
- if you need more functionality use interface composition to build a larger interface, take ReadDirFS or
StatFS
as an example
- depending on your personal opinion this might be good or bad news
- we will not see generics in a 1.x release
- Ardan Labs three part blog article series about generics
- (since some time already) there are two ways to try out generics:
- compile the
go2go
translation tool from thedev.go2go
branch of the Go repo (instructions) - use the go2go playgound
- compile the
func print[T any](value T) {
fmt.Printf("type=%T\tvalue=%#v\n", value, value)
}
print([]int{1, 2, 3, 4})
print("Hello, Golang Leipzig!")
[T any]
is the type parameter listany
is a type constraint (limiting the set of allowed types that can be used forT
)any
means "unconstrained" or allow any type forT
type Number interface {
type int, float64
}
func sum[T, S Number](a T, b S) S {
return S(a) + b
}
sum(1, 3.1415)
- a type parameter list can contain multiple type identifiers
- ... we will talk likely have a separate talk that covers Generics in depth