
Go 1.9 is released - techietim
https://blog.golang.org/go1.9
======
old-gregg
In case someone cares about these things, I compared the build times and the
binary sizes for 1.9 vs 1.8.3 using the open source project we maintain [1].
This is on a 6-core i7-5280K:

Build time with 1.8.3:

    
    
       real	0m7.533s
       user	0m36.913s
       sys	0m2.856s
    
    

Build time with 1.9:

    
    
       real	0m6.830s
       user	0m35.082s
       sys	0m2.384s
    
    

Binary size:

    
    
       1.8.3 : 19929736 bytes
       1.9   : 20004424 bytes
    
    

So... looks like the multi-threaded compilation indeed delivers better build
times, but the binary size has increased slightly.

[1] You can git-clone and try yourself:
[https://github.com/gravitational/teleport](https://github.com/gravitational/teleport)

~~~
amenghra
Unless you perform a proper statistical analysis it's unfair to draw a
conclusion from a single run.

Furthermore, when I see a second run that's faster than the first one, I
immediately wonder if it's the cache being cold for the first run and warm for
the second.

While I have your attention, [https://zedshaw.com/archive/programmers-need-to-
learn-statis...](https://zedshaw.com/archive/programmers-need-to-learn-
statistics-or-i-will-kill-them-all/) is worth reading.

~~~
hueving
"Programmers Need To Learn Statistics Or I Will Kill Them All"... What an
insufferable asshat.

PSA: There is no reason to behave like this and this is an incredible way to
alienate a bunch of people. You either offend people directly with the murder
implication or they don't take you seriously because you sound like you're
throwing such an extended temper tantrum that you managed to write it all in a
blog.

~~~
baq
or you can stop being offended by words put out on the internet by
strangers... which is what i always recommended to basically everyone.

~~~
pron
Or, you can be _not_ offended and still criticise someone for being an asshat.

------
alpb
t.Helper() is certainly going to be very useful. I often implement functions
like:

    
    
        func testServer(t *testing.T, port int) {
            ...do stuff...
            if err != nil { t.Fatalf("failed to start server: %+v", err) } 
        }
    

similarly you can have

    
    
        func assertMapEquals(t *testing.T, a, b map[string]int)
    

It lets you hide such helper methods from the test failure's stack trace
(where t.Fatal is actually called), making test errors more readable.

~~~
azinman2
Yes indeed this is totally awesome. It’s a problem that occurs on any
platform, and not only for testing. I often see this problem with logging as
well, where some validation/helper function logs an error separate from the
context it occurred in, potentially making it hard to trace without a
stacktrace logged as well.

~~~
throw4625
This is the biggest problem with Go errors and one of my biggest gripes with
the language. Exceptions have stacktraces that give you context about where
the error originated. Go errors don't have this and it costs me a lot of time
debugging
things.[https://godoc.org/github.com/pkg/errors](https://godoc.org/github.com/pkg/errors)
helps, but it's still more of a pain than it should be.

~~~
cpuguy83
Errors can be anything. It's just an interface.

~~~
stouset
Except you don't get to control the specific error type returned by packages
you import. So sure, you could get stack traces for _your_ code, but not for
your dependencies.

It infuriates me when go proponents try and sweep bad language decisions under
the rug with half-fixes.

[https://twitter.com/codebeeCA/status/885302657178587136](https://twitter.com/codebeeCA/status/885302657178587136)

~~~
jimjimjim
it infuriates me when third-party stuff in other languages throws exceptions
and you end up needing to check everything anyway.

exceptions are a curse.

~~~
9t3h4r3o5w1a4w2
> it infuriates me when third-party stuff in other languages throws exceptions
> and you end up needing to check everything anyway. exceptions are a curse.

Anything can panic in Go. Go gives absolutely no guarantee something cannot
panic. Errors as values are just a convention. So exceptions are a curse but
Go has an inferior exception system, panics, but they are still exceptions.

The solution is checked exceptions.

------
zkanda
In case you guys didn't know, there's multiple release party in different
parts of the world:
[https://github.com/golang/cowg/blob/master/events/2017-08-go...](https://github.com/golang/cowg/blob/master/events/2017-08-go1.9-release-
party.md)

Come join if your near the area.

~~~
baby
None in London :(

------
tschellenbach
Nice can't wait to run some of our benchmarks against this. Go has the awesome
property of always becoming a little bit faster every release. It's like your
code becomes better without doing anything. Love it :)

~~~
rjammala
This is what they mentioned in 2015. See slide 3 in this pdf:
[https://talks.golang.org/2015/go-gc.pdf](https://talks.golang.org/2015/go-
gc.pdf)

------
cristaloleg
Please remember that sync.Map isn't type safe and is more optimised for reads.

~~~
kjksf
interface{} and therefore sync.Map is type safe.

[https://en.wikipedia.org/wiki/Type_safety](https://en.wikipedia.org/wiki/Type_safety)

> Type enforcement can be static, catching potential errors at compile time,
> or dynamic, associating type information with values at run-time and
> consulting them as needed to detect imminent errors, or a combination of
> both.

interface{} is type-checked at runtime. It's type-safe because because you
can't e.g. fish out an integer out of interface{} value that represents a
string. Runtime won't allow it.

You can either extract a string or the runtime will crash if you insist on
extracting anything else. Unless you use unsafe package, in which case you
explicitly want to skip type-safety.

~~~
ryeguy
When "type safe" is mentioned without qualification, it almost always refers
to static type safety. This is one of those times. So no, the sync.Map
container is not typesafe like a regular map is.

~~~
kjksf
According to whom? Certainly not according to wikipedia.

Given that it's a pretty big distinction I would think it's on the speaker to
be un-ambiguous and say "it's not statically type safe" vs. ambiguous "type
safe".

I've certainly seen my share of people claiming that "interface{} is just like
void * in C" when they speak about Go's (lack of) type safety.

I also don't see how insisting on accurate and un-ambiguous terminology ticks
people off so much to downvote. I imagine they think I said something much
more incorrect than I did.

~~~
andrewjw
"type safe" has come to mean "statically type safe" over time in common
conversation. You were downvoted because this intended usage was clear to the
people who downvoted you and their perception of your comment was that it
provided no value, e.g. was a nitpick.

I would note that the Wikipedia page does not take as strong a position as you
seem to imply, reading:

> In the context of static (compile-time) type systems, type safety usually
> involves (among other things) a guarantee that the eventual value of any
> expression will be a legitimate member of that expression's static type. The
> precise requirement is more subtle than this — see, for example, subtype and
> polymorphism for complications.

Since golang is statically typed, type safety is generally understood to mean
static type safety.

------
Scorpiion
In the release notes it says:

    
    
      "Mutex is now more fair."
    

Source: [https://golang.org/doc/go1.9#sync](https://golang.org/doc/go1.9#sync)

Does anyone know what that means?

~~~
emfree
You piqued my curiosity :) A comment in the source for the release notes
([https://github.com/golang/go/blob/master/doc/go1.9.html#L922](https://github.com/golang/go/blob/master/doc/go1.9.html#L922))
points to the relevant change: [https://go-
review.googlesource.com/c/go/+/34310](https://go-
review.googlesource.com/c/go/+/34310), which in turn links to this issue:
[https://github.com/golang/go/issues/13086](https://github.com/golang/go/issues/13086)

~~~
Scorpiion
Ah, thanks for the links.

I googled a little bit and found some good info, I guess I had forgotten a
little bit of the concepts of mutex fairness/unfairness. I found a very nice
explanation on cs.stackexchange:

    
    
      "My understanding is that most popular implementations of a mutex (e.g. std::mutex in C++) do not guarantee fairness -- that is, they do not guarantee that in instances of contention, the lock will be acquired by threads in the order that they called lock(). In fact, it is even possible (although hopefully uncommon) that in cases of high contention, some of the threads waiting to acquire the mutex might never acquire it."
    

Source: [https://cs.stackexchange.com/questions/70125/why-are-most-
mu...](https://cs.stackexchange.com/questions/70125/why-are-most-mutex-
implementations-unfair)

With that computer science clarification, I think the comment "Mutex is now
more fair" and the detailed description "Unfair wait time is now limited to
1ms" makes it a lot clearer.

Great improvement I think! It's one of those things that you don't notice
until you have a bug, but it's really nice to never get that bug in the first
place. =)

------
tmaly
I am looking forward to

1\. runtime/pprof package now include symbol information

2\. Concurrent Map

3\. Profiler Labels

4\. database/sql reuse of cached statements

5\. The os package now uses the internal runtime poller for file I/O.

~~~
Diederich
> 4\. database/sql reuse of cached statements

!! that wasn't a thing until now?

~~~
bradfitz
It was. That summary is a bit of a simplification.

See
[https://golang.org/doc/go1.9#database/sql](https://golang.org/doc/go1.9#database/sql)

Go 1.9 adds reuse of statement handles created off an ephemeral transaction
too. But all the other statement handle cases have cached from day 1.

------
e12e
Does anyone know of compile-time benchmarks spanning 1.4 through 1.9, along
the lines of [1]?

I see there's (more) parallel compilation in 1.9 - so that should improve
elapsed time (but not reduce cpu time) of compilation.

Would be nice to know if 1.9 is (still) on track catch up to/pass 1.4.

[1] [https://dave.cheney.net/2016/11/19/go-1-8-toolchain-
improvem...](https://dave.cheney.net/2016/11/19/go-1-8-toolchain-improvements)

~~~
dilap
I was curious so I downloaded Go 1.4, and tested against 1.9 on an old version
of a project I have (backend for Mafia Watch), about 30K lines of Go,
including a few 3rd party dependencies.

Go 1.4: Around 2.1s Go 1.9: Around 2.5s

So within 20% of 1.4, not bad. That's on an old MacBook Air, dual core 1.7 GHz
i7, 8GB ram.

And of course the binary performance and GC pause times w/ 1.9 will be much
better.

Here's the raw times:
[https://pastebin.com/ULDHPmVu](https://pastebin.com/ULDHPmVu)

Two awesome things:

It was super-easy and fast to download and compile Go 1.4

It was completely painless to compile my old code with Go 1.9

I fucking love how nice it is to work with the Go ecosystem. <3

------
ivan4th
I was looking forward to the fix for the dreaded Linux namespace handling
problem: [https://www.weave.works/blog/linux-namespaces-and-go-don-
t-m...](https://www.weave.works/blog/linux-namespaces-and-go-don-t-mix) which
kind of makes Go suck for many important container-related tasks. But
apparently the effort has stalled... [https://go-
review.googlesource.com/c/go/+/46033](https://go-
review.googlesource.com/c/go/+/46033)

~~~
valarauca1
There really aren't great solutions to this in C/C++ having one application
share state/memory across namespaces/users is a v hard problem

~~~
dullgiulio
This has been discussed and the discussion derailed very quickly ("Go is a
joke, my language has it bigger, blah blah".)

Reality is that the Linux Kernel makes a big confusion between processes and
threads in the userspace APIs.

Locking to threads is a solution that works but also sucks and defeats the
niceties of Go N:M model. But that's the only way: if you use that broken
system calls API you should know better.

------
alphaalpha101
So this new concurrent map? Am I right in understanding it's designed for
cases where you have a map shared between goroutines but where each goroutine
essentially owns some subset of the keys in the map?

So basically it's designed for cases like 'I have N goroutines and each one
owns 1/N keys'?

~~~
artursapek
It could just be one map shared by many goroutines, which normally causes a
panic:

    
    
        fatal error: concurrent map writes

~~~
freecodyx
i am dealing with this problem right now. also i have a big problem with
deepclone,

I did a big rewrite of a current project, and clearly it was badly designed :(

------
riobard
I'm wondering if we could abuse type alias to fake generics somehow? E.g.

    
    
      // file tree.go
      type T = YourConcreteType
      type TreeNode struct {
        Value T
      }
      // rest of tree implementation
    
    

Then you can just copy the file and replace YourConcreteType at the top and
voila!

Seems simpler to use than the unicode hack here
[https://www.reddit.com/r/rust/comments/5penft/parallelizing_...](https://www.reddit.com/r/rust/comments/5penft/parallelizing_enjarify_in_go_and_rust/dcsgk7n/)

~~~
stewbrew
Now make that a compile time thing that happens on imports and that doesn't
generate temporary source files and whoop you have modules with generics.
Oops, I forgot that there are some unsolvable obstacles to be resolved.

~~~
jhgb
I have been wondering for quite some time how one could implement that. That
is, not in the sense of how to _code_ that, but rather how few changes one
would have to make to the language to get as many effects as possible in the
direction of genericity. There is some inspiration in Lua, Scheme48 and some
dialects of ML (functors, I believe?) in the form of "higher-order modules",
where the module (would be package in Go?) could have parameters that you'd
have to supply when importing it. The things you could obviously supply would
be at least constants, functions and types. (One _might_ look at functions as
types of computational processes, though, and at function
signatures/interfaces as their respective type classes. This perspective could
subsume functions as types, and perhaps integers as nullary functions
returning an integer.) The question is how to reasonably do the import
strings. Good thing about Go is that you already have provisions in the
language in the sense that the string can be technically arbitrary. A subset
of the reflection interface could additionally be evaluated at compile time to
provide for ad-hoc specializations of generic code by writing straightforward
code that would be easily eliminated/specialized in a module instantiation
(like loops over struct fields etc.)

~~~
stewbrew
Are you saying, it wouldn't be too difficult to implement this in the go
compiler but the crucial question is (just) the syntax of the import string?

~~~
jhgb
The interface to the feature is perhaps more important than the complexity of
the implementation because it will affect many more people - only a few
programmers will work on the compiler but tens of thousands of programmers
will be writing code using it. I make no claims as to how complex this would
be to implement, but it probably wouldn't stand out. The interesting thing is
that this shouldn't necessitate any changes in the language of generic modules
(no <>s and such). It merely parameterizes some types and constants in a
module. As such, after a certain phase in compilation, the process is the same
as for a non-generic module so perhaps it's a low-complexity change in the
implementation, too (not just in the language spec).

~~~
stewbrew
> no <>s and such

Funny. The first thing that came to mind was:

    
    
        import (
            bar "github.com/name/bar"
            baz "github.com/name/baz"
            foo "github.com/name/foo"
            foo_bar "foo<A=bar, B=baz>"
        )

~~~
jhgb
You could, but the strings are not the language proper. There's, e.g., no
relational expressions in your import strings (yet!), so there's no ambiguity
in parsing it. I'd actually use parentheses anyway, since type parameters are
still parameters (this could give the parameter list a "Pythonic" syntax which
has been shown to work well already).

~~~
stewbrew
I don't fully understand your comment ("no relational expressions in your
import strings") but parentheses are valid characters in filenames (thus
URLs). I don't think Python is the best reference here.

------
kokwak
Please add enum class

~~~
rgbrenner
[https://golang.org/ref/spec#Iota](https://golang.org/ref/spec#Iota) ?

~~~
kokwak
Thanks and please check this proposal for go2:
[https://github.com/golang/go/issues/19814](https://github.com/golang/go/issues/19814)
Thumbs up if you like it.

