Send me an email!
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
.