What's happening in Go tip (2013-09-07)
Welcome back to yet another update on Go tip. We’ll be looking at another batch of smaller changes from all over the place; there’s something for everyone.
And if you’re waiting for some juicier changes, let me just say that they’re on my radar, but I am reserving them for the finale. Well, really for the big hole that the feature freeze will cause.
Also, I’m sorry for releasing this article a day late. I hope I didn’t ruin anyone’s Friday at work :-( – I will try to release the next article on time again.
What’s happening ¶
This week we will be looking at:
- Reusable Writer in compress/flate
- Improvements to text/template
- More control over database/sql’s connection pool
- The netgo build tag
- Small tooling changes
Reusable Writer in compress/flate ¶
Relevant CLs: CL 12953048, CL 13171046, CL 13435043, CL 12894043
Continuing the trend of less garbage, the Writers in compress/flate
, compress/zlib
and compress/gzip
have a new
Reset()
method, which allows resetting a Writer’s internal state without needing to allocate new memory. According to
issue 6138, this saves 1.4 MB of allocations per Writer you would have to create.
In a somewhat related change, a test in archive/zip
has been brought down from 34 seconds to 0.23 seconds, by avoiding
an allocation in archive/zip
itself and by not using compress/flate
in the test at all. While this hardly affects
people who use archive/zip
, it’s a welcome speedup to anyone who has to run Go’s entire test suite.
Improvements to text/template ¶
Relevant CLs: CL 13091045, CL 13509046, CL 13327043
Two small additions to text/template
(and, by extension, html/template
) might make writing templates just a bit
easier.
The first addition is {{else if}}
, which can be used instead of {{else}}{{if}}
. Naturally this also means one less
level of nesting, so that this:
{{if A}}
a
{{else}}
{{if B}}
b
{{end}}
{{end}}
will turn into this:
{{if A}}
a
{{else if B}}
b
{{end}}
A welcome simplification!
The second addition are built-in comparison functions for basic types, that is booleans, (unsigned) integers, floats,
complex numbers and strings. The eq
(equality) comparison is special in that it accepts a variable number of arguments
(at least two), comparing the first argument to all the other arguments in an OR relation. So {{eq arg1 arg2 arg3}}
would be equivalent to arg1==arg2 || arg1==arg3
. It is important to note that eq
is an ordinary function, so there’s
no short circuit and all arguments will be evaluated.
Furthermore, these functions are a bit more lax than the Go type system, allowing comparison between different sizes of
the same type (e.g. int32
and int16
), as well as different types with the same underlying type (e.g. type Foo int
and int
)
Here’s a table of the new functions as well as their equivalent Go syntax:
Operator | Function |
---|---|
== | eq |
>= | ge |
> | gt |
<= | le |
< | lt |
!= | ne |
More control over database/sql’s connection pool ¶
Relevant CLs: CL 10726044
A long awaited improvement (at least by some people) is more control over the connection pool managed by database/sql
.
Thanks to CL 10726044 it is now possible to limited the total number of simultaneous open connections, by using
(*DB).SetMaxOpenConns(int)
.
It is an important addition to the already present SetMaxIdleConns
. Limiting the number of idle connections wouldn’t
prevent an unbounded number of connections to be created if they were needed, it would only close most of them once
done. This could still lead to more connections than wanted, hitting database or resource limits.
By setting the maximum number of open connections, however, we ensure that we will never exceed that number of connections. Also, the maximum number of open connections can be bigger than the maximum number of idle connections, allowing bursts without keeping all connections around. This should remove the need for custom pooling, limits and semaphores in a lot of database code.
The netgo build tag ¶
Relevant CLs: CL 7100050
Go binaries, if not using cgo, are usually statically linked. When importing the net
package (directly or indirectly),
however, one ends up with a dynamically linked binary, linking against libc. That’s because the net
package, by
default, uses cgo to use the system’s resolver, to support for example LDAP. The net
package does come with a pure-Go
resolver. Until now, it was only used when cgo wasn’t enabled, which means compiling the standard library (or at least
net
) as well as your own package with CGO_ENABLED=0
. But that has the downside of disabling cgo for your entire
project, which might not be desirable.
A new build tag, netgo
, alleviates this problem by providing a way to build the standard library and your project with
a pure-Go net
package while still enabling cgo for other uses. In order to reinstall the standard library with
netgo
, you run
go install -a -tags netgo std
You also need to specify -tags netgo
when building your own package, otherwise cgo will overrule and rebuild net
every time you build your package. This does allow installing a netgo
standard library as the default with cgo as a
working alternative, but it also has the added cost of recompiling the net
package every time you do not use the
netgo
tag.
Small tooling changes ¶
There are two small changes to tooling that are worth mentioning.
Deletion of go doc ¶
Relevant CLs: CL 12974043
The first is the deletion of go doc
. Now, mind you, go doc
is not the same as godoc
. go doc
accepts different
(more limited) arguments than godoc
and apparently the consensus was to remove it and focus on improving godoc
instead. Issue 4849 kind of leads up to the deletion and CL 12974043 is ultimatively deleting it.
This change goes to show that Go’s compatibility promises only cover the language and standard library, not tools.
go get for git repositories ¶
Relevant CLs: CL 12923043, some more I unfortunately do not have the numbers of.
If you ever used go get
on a git repository and later went to look at the actual clone, you might have noticed that
HEAD was in a detached state, and that every go get -u
would put it back in detached state, with HEAD pointing at a
specific commit on a remote branch.
And even though that isn’t technically a problem (you could still just check out the master branch), it would lead to confusion and occasional loss of data when one wasn’t aware of the fact.
In Go 1.2, however, go get
will always create a “proper” (as in expected) clone, with an active master branch, and go get -u
will use git pull
and all its effects, such as aborting in case of conflicts or uncommitted changes. Old
clones from before Go 1.2 will automatically be updated to the new format by go get -u
.