Skip to content

golang-leipzig/go-1.16-and-beyond

Repository files navigation

A quick tour of Go 1.16 @ 16th Golang Leipzig Meetup

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! 🎉 🎆

  • ⚠️ GO111MODULE=on is now the default, i.e. go tools work in go modules mode by default
  • go build and go test do not modify your go.mod, go.sum anymore
    • those two commands report if an module or checksum needs to be added or updated
    • use go get or go mod tidy to do tha

Other

  • 🎉 runtime/metrics is a new package that provides a stable interface for accessing runtime metrics
  • GODEBUG=inittrace=1 prints execution time and memory allocation for all init 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> (running strip <binary-file> will remove them all)
    • symbol pruning refers to the removal of symbols that are unused, e.g. uncalled functions from imported libraries

A deeper look on the new embed package

  • 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 or embed.FS
    • use embed.FS when importing multiple (a tree of) files into a variable
  • using the embed directive requires to import embed even when using string or []byte variables (use blank import `import _ "embed")
  • // go:embed pattern [pattern...] where paths use path.Match patterns
    • string 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 embed dir/.foo but // go:embed dir will not!
  • 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

os and io/fs

  • 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 call stat 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 use filepath.WalkDir instead of filepath.Walk, filepath.WalkDir passes fs.DirEntry instead of os.FileInfo into the WalkFn
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
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

Generics

The proposal got accepted 🎉

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!")

playground

  • [T any] is the type parameter list
    • any is a type constraint (limiting the set of allowed types that can be used for T)
    • any means "unconstrained" or allow any type for T
type Number interface {
	type int, float64
}

func sum[T, S Number](a T, b S) S {
	return S(a) + b
}

sum(1, 3.1415)

playground

  • a type parameter list can contain multiple type identifiers
  • ... we will talk likely have a separate talk that covers Generics in depth

Questions ❓

About

A talk about Go's 1.16 release as well as an outlook on the generics proposal.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published