
Upcoming Go protobuf release - stablemap
https://groups.google.com/forum/#!topic/golang-nuts/F5xFHTfwRnY
======
lobster_johnson
The three breaking changes are interesting in how, one by one, they describe
flaws in the Go language (and I say that as someone whose day job is Go
development).

The first breaking change means unkeyed literals such as Foo{"bar"} no longer
work. This particular Go feature (which arguably came from C) is so open to
future compatibility breakage that I wish it had never been included. I prefer
Rust's approach here, where fields always have to be speciifed, but a ::new()
constructor can be furnished to make fieldless construction possible through
the type (as opposed to Go's NewFoo() style which is semantically disconnected
from the type).

The second one, about structs no longer being usable as map keys or comparable
with ==, is a bit more esoteric, but it does demonstrate how Go's type system
is too weak to allow such a change to be made without breakage. In Rust or
C++, this would presumably have been accomplished with an equality trait, so
that the new struct _could_ be made comparable with ==.

The third one, about breaking reflect.DeepEqual(), also reveals how the lack
of trait support at the language level exposes cracks in the language. When a
user is forced to use a blunt tool such as DeepEqual(), which disconnects the
equality code from the underlying type being used, then this is what you get.
That said, I'm not sure why Protobuf can't optionally generate equality
methods for the types it generates in the first place, which is something Gogo
can do [1].

Go is a great language, but it's things like this that give me Rust envy.

[1]
[https://github.com/gogo/protobuf/blob/master/plugin/equal/eq...](https://github.com/gogo/protobuf/blob/master/plugin/equal/equal.go)

~~~
jerf
"This particular Go feature (which arguably came from C) is so open to future
compatibility breakage that I wish it had never been included."

This is the community consensus view. I strongly disagree with it. Unkeyed
literals are useful for when you _want_ to get a compile-time error if any
fields change, which is common in tuple-like structs. If there is anything
wrong with this, it is that in theory you ought to be able to specify at the
type declaration whether you must use unkeyed (IMHO a valid use case), must
use keyed, or may use either. However this would not generally fit with Go's
philosophy.

As a consequence of that theory, I would never use unkeyed literals to create
a generated type; too likely that something will change in the generated type
with future generators, exactly as I stated.

I suppose this could be layered on in another linter, although since the
community and I part ways here even if I wrote "nobody" would use it.

"The second one, about structs no longer being usable as map keys or
comparable with ==,"

One of the weirdest things about Go to me is the whiff on making several
operations interfaces, like how Python has __del__ and such. == is a
particularly weird case; the rules for == are downright dynamic language-ish:
[https://golang.org/ref/spec#Comparison_operators](https://golang.org/ref/spec#Comparison_operators).
I imagine they may have considered this "operator overloading" but IMHO that's
only a problem on operators that come with a lot of implicit semantics like +,
not the "lookup operator".

~~~
perfmode
Unkeyed literals wont produce a compiler error if fields of the same type and
position are replaced. Or if a field is “renamed” to something semantically
distinct.

~~~
jerf
I tend to use lots of little types, so I don't generally end up with {int,
int, int} but {Width, Height, Depth} or something. In practice I don't have
this problem. YMMV depending on your own practices.

------
weinzierl
Nothing wrong with Go protobuf, but if you need a lean and mean Protocol
Buffers implementation I can recommend Nanopb. It's just a few kB and you can
run it even malloc free.

[1] [http://jpa.kapsi.fi/nanopb/](http://jpa.kapsi.fi/nanopb/)

~~~
Cyph0n
If only I had known this existed last year... I linked in Google's C++ library
compiled for ARM to a project and it bloated the binary to ~12 MB...

~~~
jperras
We use nanopb on embedded devices; it's quite small & efficient. No real
complaints.

------
cjhanks
Hmm, this seems like it might create security leaks for developers using
protobuf at public interfaces. They should probably have some kind of static
configuration variable `DefaultDiscardUnknown = true`.

------
akmittal
will this fix slow gRPC performance in Go compared to Java/C++ or that is
different issue.

~~~
cube2222
Do you have any sources about gRPC being slow in Go?

~~~
guilhas
Not sure, but I saw this video: At 26:16 Gopherfest 2017: Upspin (Rob Pike) -
[https://www.youtube.com/watch?v=ENLWEfi0Tkg](https://www.youtube.com/watch?v=ENLWEfi0Tkg)

~~~
dfawley
That specific problem was resolved in July last year:
[https://github.com/grpc/grpc-go/pull/1310](https://github.com/grpc/grpc-
go/pull/1310) [https://github.com/grpc/grpc-
go/issues/1043](https://github.com/grpc/grpc-go/issues/1043)

------
ohnoesjmr
I wonder how this compares with Gogoproto. Nobody in their sane mind uses the
standard protobuf package anyway.

~~~
maxaf
I've been using the standard protobuf package for years, yet I am entirely
sane. My mother had me tested.

