News for hackers. Stuff that matters.
Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @12:00PM (#22444193)
Here's an example of why Go's simplicity is complicated:

Say I want to take a uuid.UUID [1] and use it as my id type for some database structs.

At first, I just use naked UUIDs as the struct field types, but as my project grows, I find that it would be nice to give them all unique types to both avoid mixups and to make all my query functions clearer as to which id they are using.

    type DogId uuid.UUID
    type CatId uuid.UUID
I go to run my tests (thank goodness I have tests for my queries) and everything breaks! Postgres is complaining that I'm trying to use bytes as a UUID. What gives? When I remove the type definition and use naked UUIDs, it works fine!

The issue is Go encourages reflection for this use-case. The Scan() and Value() methods of a type tell the sql driver how to (de)serialize the type. uuid.UUID has those methods, but when I use a type definition around UUID, it loses those methods.

So the correct way to wrap a UUID to use in your DB is this:

    type DogId struct { uuid.UUID }
    type CatId struct { uuid.UUID }
Go promised me that I wouldn't have to deal with such weird specific knowledge of its semantics. But alas I always do.

[1] https://github.com/google/uuid

EDIT: This issue also affects encoding/json. You can see it in this playground for yourself! https://play.golang.org/p/erfcSIe-Z7b

EDIT: I wrongly used type aliases in the original example, but my issue is with type definitions (`type X Y` instead of `type X = Y`). So all you commenters saying that I did the wrong thing, have another look!

Re:I Want Off Mr. Golang's Wild Ride by hajile on Friday February 28, 2020 @12:11PM (#22444269)
Is there even a single go abstraction that doesn't leak it's guts everywhere?
Re:I Want Off Mr. Golang's Wild Ride by thedance on Friday February 28, 2020 @12:32PM (#22444477)
There aren't any abstractions in any language or library that don't leak everything about what they are trying to hide as well as everything about their own implementation. That's just life. It's impossible to hide complexity. Whatever wraps one thing will be strictly more complex than the wrapped thing was.
Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @12:40PM (#22444549)
This just isn't true!

Haskell's json/sql marshalling do not use runtime reflection but instead ad hoc polymorphism, so when I create (or even derive automatically!) a marshalling instance, it is pretty easy for me to reason about what will happen statically. Haskell's Generic & newtype-deriving go a long way here, and are good examples of principled abstractions that do not leak.

Haskell's conduit (and other streaming libraries) is another good example. I use them to create programs that process things in constant memory, and when I compose them (e.g. with operators like =$= or .| in conduit), the resulting program streams in constant memory. I have built entire systems (CLIs, batch jobs, event processors, etc) on top of this abstraction and conduit itself has never leaked.

Re:I Want Off Mr. Golang's Wild Ride by wronghorse on Friday February 28, 2020 @05:03PM (#22446838)
I believe Rust's serde library is similar when it comes to JSON. It also gives you the option to choose how strictly you want to enforce the types.
Re:I Want Off Mr. Golang's Wild Ride by pmarreck on Friday February 28, 2020 @01:11PM (#22444894)
This is funny because after almost 4 years of working with Elixir and watching Go from arms’ length, I literally see NONE of the criticisms regularly leveled at Go. This is not an exaggeration. In fact, Elixir has few criticisms at all to begin with, and it’s driven very large sites already at this point.

(Yeah, it can’t compile easily distributable self contained binaries. It’s not (yet) designed for that.)

Not intending to start a language war, but your argument is basically the beaten wife claiming this is just standard treatment from husbands. This is my counterexample.

Re:I Want Off Mr. Golang's Wild Ride by anthony_doan on Friday February 28, 2020 @01:40PM (#22445149)
Elixir is a fantastic and small language. Jose Valim kept it reasonable.

It just have so much depth with concurrency. The actor model is amazing and easy to think about too.

I'm not entirely sure they overlap completely but the concurrency model is superb. I will probably only use Elixir for web application from now on (unless they don't have packages for certain API). Chris have made web development possible and many awesome people have contributed (POW package is just lovely).

Re:I Want Off Mr. Golang's Wild Ride by swat535 on Friday February 28, 2020 @02:30PM (#22445578)
Elixir is Erlang anyway. The only difference between the two is basically syntax and a couple of bonuses in the Elixir STDLib, most of which wraps existing Erlang functions.

You're praising Erlang's concurrency model, there's no such thing as Elixir concurrency model.

Re:I Want Off Mr. Golang's Wild Ride by anthony_doan on Saturday February 29, 2020 @12:57PM (#22451892)
Yeah I understand that but not many people do Erlang from Elixir from my experiences. Also I find Elixir community is better for me as a web developer than Erlang.

But it's also inescapable to ignore Erlang when you dive deeper into the actor model. Several good actor model books are Erlang only. Unfortunately many people, including myself, ever actually do anything hardcore with Actor Model. There is a good blog post about several skill stages of erlang/elxir and OTP was at the very top in term of few people actually uses it. I can't recall it the author =/.

Actually, I like Elixir package management system and command line tool is much better. They recently have the release command line tool. Elixir have several more differences?

Re:I Want Off Mr. Golang's Wild Ride by PopeDotNinja on Saturday February 29, 2020 @06:06AM (#22450046)
I tell people Elixir is just pretty Erlang.
Re:I Want Off Mr. Golang's Wild Ride by Thaxll on Friday February 28, 2020 @02:06PM (#22445359)
The reason is because Go is very popular where Elixir is not, if Elixir was standing where Go is now it would be pretty much the same, I guaranty you that.
Re:I Want Off Mr. Golang's Wild Ride by hajile on Friday February 28, 2020 @02:44PM (#22445684)
Erlang is a stable language that has been around for a long time (almost 35 years now). It's used for way more mission-critical code than golang is ever likely to be used for. It's weird syntax and performance tradeoffs are very well known, but you still won't see anywhere near the number of complaints that you see against golang.
Re:I Want Off Mr. Golang's Wild Ride by Thaxll on Friday February 28, 2020 @03:17PM (#22445933)
Erlang is less and less used in telecoms and it's the only place if was really used, lot of things have switch to C/C++/Java.

As for the reason why it has less complains it's pretty simple no one uses Erlang and it's a niche, it's not a generic purpose language. I can't even tell a single known application or library written in Erlang.

Re:I Want Off Mr. Golang's Wild Ride by hajile on Friday February 28, 2020 @03:52PM (#22446254)
IBM Cloudant runs everything CouchDB which is written in Erlang as does Amazon for SimpleDB. WhatsApp and a bunch of Pinterest are written in Erlang (they may actually be in Elixir, but on BEAM).

To my knowledge Ericsson still writes most things in Erlang. Yahoo uses it for a couple large services. My company use PagerDuty which is also written on BEAM.

I'm sure there are many, many other things in not familiar with, but claims of Erlang's demise are greatly exaggerated.

Re:I Want Off Mr. Golang's Wild Ride by ptr on Friday February 28, 2020 @04:09PM (#22446388)
Erlang is mainly used in the control plane at Ericsson -- you'd never write a DSP in it for example. Most code is sadly not Erlang.
Re:I Want Off Mr. Golang's Wild Ride by pmarreck on Friday February 28, 2020 @03:47PM (#22446213)
Ah yes. Whoever's heard of Whatsapp, Pinterest, Discord, and Goldman Sachs? https://codesync.global/media/successful-companies-using-eli...
Re:I Want Off Mr. Golang's Wild Ride by pjmlp on Saturday February 29, 2020 @04:57AM (#22449880)
Just like Go only matters mostly to Docker and K8s shops.
Re:I Want Off Mr. Golang's Wild Ride by jstimpfle on Saturday February 29, 2020 @07:50PM (#22454336)
ejabberd is one that I had installed at some point.
Re:I Want Off Mr. Golang's Wild Ride by dnr on Friday February 28, 2020 @02:36PM (#22445625)
If you were using Go for those four years, you'd also see very little of the criticisms regularly leveled at Go. What you see on the internet is the union of everyone's complaints and frustrations. Each individual sees only some of those, maybe even none depending on the type of work they're doing. And the ones that are generally happy don't tend to post big rants, so the overall impression of an outsider can be pretty skewed.
Re:I Want Off Mr. Golang's Wild Ride by pmarreck on Friday February 28, 2020 @04:15PM (#22446435)
> If you were using Go for those four years, you'd also see very little of the criticisms regularly leveled at Go.

That's bullshit. When I worked in the Ruby on Rails space, I saw critisms quite often... for example of the "one size fits all" way-too-large-surface-area library design (see: ActiveSupport) or the "fat model" design trend at the time... I even PRODUCED some of these criticisms myself. Heck, the bug that made me leave the space took a month to track down and had to do with nondeterminate behavior when merging a Hash with a HashWithIndifferentAccess (this was not my code, I would have not written it the way it was written, but it was a bug I was assigned to of someone else's code) because the Ruby language did not see these as two distinct "types" and simply went ahead as if they were both regular Hashes, which caused HWIA keys to get overwritten unexpectedly/nondeterministically... that was the last straw at the time.

And when I worked in .NET/ASP prior to that, I saw (and witnessed) MANY criticisms of the language and API such as how easy it was to produce difficult-to-test spaghetti code.

And while all this was happening I was also working on frontend code in JS and needless to say there have been A LOT of JS criticisms over the years and I've seen most of them.

So yeah, maybe try again with less BS. The biggest criticism I can produce of Elixir (and more generally the BEAM VM) is that too few people understand its advantages and too many people actively misinform others about it. (OK, one more criticism, but it is a more general criticism of functional immutable languages: A handful of algorithms perform suboptimally in a language that does not even permit mutation, relative to a language that does.)

Re:I Want Off Mr. Golang's Wild Ride by dnr on Friday February 28, 2020 @05:10PM (#22446884)
I think you might be reading an unintended meaning into that sentence. I'm talking about the experience of using Go vs. what people write about it, not about your experiences with other languages (which I have no intention of invalidating). I was pointing out that sometimes one can get a skewed perspective of the typical experience by reading blog posts and things (which by definition are written by the more vocal members of a community).

I did use Go professionally for about five years, and read lots of criticisms of it (and still do out of curiosity). Most of them struck me as just not a big deal in practice. When I had to write some list-processing code that could be greatly simplified with generics (a few times per year), I just sighed and typed it out and moved on to a more interesting thing. When I had some repetitive error-handling code, I refactored it or wrote some helper functions. The dependency stuff was annoying when starting a new project, but once you pick a dependency manager/vendoring tool it's fairly straightforward (and of course now this is included).

Certainly, the language and ecosystem has warts and frustrating things. Maybe Elixir has fewer warts, I don't know. But overall the experience of using Go is fairly smooth and boring and productive. The things that people like to complain about don't really register in day-to-day usage. That's not BS, that's my personal experience.

Re:I Want Off Mr. Golang's Wild Ride by pdimitar on Friday February 28, 2020 @10:36PM (#22448616)
Well, you might have the Stockholm syndrome. :D But yeah, we all have to deal with some idiosyncrasies with our languages/tools of choice. It’s inevitable.

For the record, I really love Elixir but it’s quite easy to swallow/ignore errors there as well. (To translate one of the Go’s criticisms.)

So I get what you’re saying. But IMO the outsiders’ perspective is valuable because it outlines stuff we have gotten used to, and they might not be willing to do that.

So such criticisms might be minor for you and me but they add much-needed nuance in the long run, I believe.

Re:I Want Off Mr. Golang's Wild Ride by pmarreck on Saturday February 29, 2020 @10:07PM (#22454858)
Fair enough.

And truth be told, a lot of the issues I encountered in the languages I mentioned were from other people’s flawed code designs, not my own.

Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @04:16PM (#22446453)
I've been using Go for years. It works, but it's mostly despite bad design issues and because of network effects/money+time put into the project. Not impressive at all.
Re:I Want Off Mr. Golang's Wild Ride by neop1x on Tuesday March 03, 2020 @05:49AM (#22473378)
You can find rants on any language because nothing can ever be perfect. Everything has pros and cons. https://yourlanguagesucks.com
Re:I Want Off Mr. Golang's Wild Ride by OceanSpray on Sunday March 01, 2020 @04:30PM (#22459503)
"It's impossible to reach absolute zero, so it's also impossible to drink chilled beverages."
Re:I Want Off Mr. Golang's Wild Ride by voldacar on Friday February 28, 2020 @05:05PM (#22446849)
heh. someone hasnt used a monad.
Re:I Want Off Mr. Golang's Wild Ride by rictic on Saturday February 29, 2020 @08:18PM (#22454454)
There is no way to avoid leaking implementation details, it's just a matter of how much you leak. Even monads leak their performance characteristics.
Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Sunday March 01, 2020 @01:35PM (#22458321)
*sometimes and not always

State, for example, doesn't leak. You never worry about the fact that it's a function `s -> (s, a)` and it gets optimized away like nuts.

Re:I Want Off Mr. Golang's Wild Ride by rictic on Monday March 02, 2020 @05:04PM (#22469533)
This is an example in favor of the fact that abstractions can't paper over performance characteristics. Users may depend on them.

In the unlikely event that there was a change to the implementation of the State monad, or to one's compiler, such that the State monad was not optimized away, it would be disruptive to users. It would probably be treated as a bug, even if the only change in behavior was in additional CPU and memory usage.

This is a corollary of Hyrum's Law.

Re:I Want Off Mr. Golang's Wild Ride by uhoh-itsmaciek on Friday February 28, 2020 @01:42PM (#22445165)
Not to mention that sql.Result (the return value of Exec) has a LastInsertId() that's an int64, so if you're using uuids, you can't use that at all and have to call Query instead and manage generated IDs yourself.
Re:I Want Off Mr. Golang's Wild Ride by HelloNurse on Friday February 28, 2020 @03:06PM (#22445856)
This is a more ridiculous symptom of bad library design than the filesystem trouble mentioned by the article.

In the real world, executing most SQL statement could be made to return a semi-useful integer according to simple and consistent rules (e.g. affected row count, -1 if there's no meaningful integer).

But the official Go documentation

https://golang.org/pkg/database/sql/#Result

makes it quite clear that the Go design committee decided to imitate a remarkably limited and inelegant MySQL function that returns the value of an auto-increment column, not even realizing that only a few statements have auto-increment columns to begin with. I'd call this a negative amount of design effort.

  LastInsertId returns the integer generated by the database
  in response to a command. Typically this will be from an
  "auto increment" column when inserting a new row. Not all
  databases support this feature, and the syntax of such
  statements varies.
(Of course, MySQL's LAST_INSERT_ID() is only bad as a building block and inspiration for a general API; in SQL queries assumptions aren't a problem and overspecialized tools can be occasionally very useful)
Re:I Want Off Mr. Golang's Wild Ride by Cthulhu_ on Friday March 06, 2020 @10:51AM (#22504499)
In a lot of cases - esp. distributed systems - it's not up to a database to generate a UUID, but the application. In theory you can have a hundred servers that generate records and send them to a central storage platform (which may or may not be a database, or event bus, etc).

UUIDs are not meant to be generated by databases.

Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @01:48PM (#22445219)
Haha yes I've long since resigned myself to using Query + explicit RETURNING for inserts

Cut 2 of 1000

Re:I Want Off Mr. Golang's Wild Ride by throwaway894345 on Friday February 28, 2020 @12:58PM (#22444744)
I agree that the standard library database tooling is really clumsy in a lot of cases, but it's the library implementation at fault, not Go itself. Notably, contrary to your last sentence, you aren't troubling yourself with "weird Go semantics", you're troubling yourself with the semantics of the database stdlib.
Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @01:15PM (#22444929)
Is there a database library that uses reflection that properly descends into type aliases? Probably not, because it isn't always what you want.

It's still fundamentally caused by Go's shitty design choices.

encoding/json is at fault as well, which is also in the stdlib and a flagship library (basically part of the language - the maintainers wouldn't even extend its struct tag parsing to allow for required fields it's so fundamental!)

Proof that this issue affects JSON: https://play.golang.org/p/erfcSIe-Z7b

Re:I Want Off Mr. Golang's Wild Ride by gwd on Friday February 28, 2020 @05:02PM (#22446835)
> It's still fundamentally caused by Go's shitty design choices.

I mean, come on. In your playground example, one way of using the UUID type inherits its methods and another doesn't. Inheritance is inherently complicated, and if you're relying on it you need to know what you're doing, no matter what language you're using. I wouldn't call that a poor design choice.

Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @05:14PM (#22446910)

    newtype NotRobPike'sUUID = NotRobPike'sUUID UUID deriving newtype (ToJSON, FromJSON)
^ not inherently complicated
Re:I Want Off Mr. Golang's Wild Ride by throwaway894345 on Friday February 28, 2020 @05:35PM (#22447050)
I'm not sure you're making the point you think you are.
Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @05:41PM (#22447085)
My point is if you Do Better than cargo cult stuff that feels nice, you can solve the original problem nicely.
Re:I Want Off Mr. Golang's Wild Ride by JohnCampbell on Friday February 28, 2020 @07:32PM (#22447731)
> Is there a database library that uses reflection that properly descends into type aliases?

The database package uses a type assertions to find the methods, not reflection.

Go types have one level of underlying type, not multiple levels as you seem to be assuming. Go is simplistic compared to other languages in this regard.

A type definition defines a new type using the underlying type of some other type.

I can understand the complaint that Go does not have the aliasing feature that you want, but the database/sql and encoding/json packages work exactly as expected given Go's simple model.

Re:I Want Off Mr. Golang's Wild Ride by skrtskrt on Friday February 28, 2020 @01:56PM (#22445284)
I'm not sure, I kind of like this?

Personally I would never create different UUID types for each DB struct, and have never seen that done.

    type DogId struct { uuid.UUID }
is type composition (Sorry if I'm not using the right term there). Isn't this exactly how you're supposed to do what you're trying to do in Go?
Re:I Want Off Mr. Golang's Wild Ride by AnimalMuppet on Friday February 28, 2020 @03:38PM (#22446119)
> Go promised me that I wouldn't have to deal with such weird specific knowledge of its semantics.

Where, specifically, did Go promise you that? I know of no languages where you don't, sooner or later, have to have weird specific knowledge of the semantics.

Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @04:15PM (#22446444)
In all of its marketing and propaganda? Constant comparisons to languages like Java bemoaning boilerplate and idiosyncrasies?

I think it's perfectly fair to say that this behavior is not in line with Go's philosophy.

Re:I Want Off Mr. Golang's Wild Ride by anonymoushn on Friday February 28, 2020 @07:10PM (#22447616)
One company asked me to write a wrapper around database/sql that adds a connection pool. This is pretty easy until you want to implement any function that returns Row, which you just can't, because you can't make one of those. Amazing.
Re:I Want Off Mr. Golang's Wild Ride by jimsmart on Tuesday March 03, 2020 @01:44PM (#22477488)
Take care, you may be wrapping your connection pool around a built-in connection pool. Furthermore, some dbs might not like log-lived connections.

http://go-database-sql.org/connection-pool.html

Re:I Want Off Mr. Golang's Wild Ride by anonymoushn on Wednesday March 04, 2020 @01:21AM (#22481608)
Sorry, my original reply was unclear. The connections would be to different replicas, and it was just a hiring task rather than something one would actually use in production.
Re:I Want Off Mr. Golang's Wild Ride by BarkMore on Friday February 28, 2020 @01:01PM (#22444772)
A type alias binds a new name to a type. All of the type’s methods are available through the new name.
Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @01:15PM (#22444931)
I fixed my comment. I didn't mean to have equal signs in there.

Proof that `type X Y` causes the issue: https://play.golang.org/p/erfcSIe-Z7b

Re:I Want Off Mr. Golang's Wild Ride by BarkMore on Friday February 28, 2020 @02:52PM (#22445752)
The type definition `type X Y` declares new type X with the underlying type of Y. X and Y share underlying types and nothing else.

This is a useful feature and there's nothing weird or special case about how this works. It's just not the aliasing feature you expected.

Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @03:07PM (#22445867)
It's still shitty and weird behavior. Not simple at all.
Re:I Want Off Mr. Golang's Wild Ride by sagichmal on Friday February 28, 2020 @01:07PM (#22444843)
Type aliases (type X = Y) are a niche feature and not meant for this use case.

If you had done e.g. type X Y you would have had more success.

Re:I Want Off Mr. Golang's Wild Ride by masklinn on Friday February 28, 2020 @01:55PM (#22445275)
I think the OP simply wrote them the wrong way around, because `type X = Y` would not have broken anything as it'd make X a trivial alias to Y, and thus would not be losing anything. Even the reflected name doesn't change from the original.

type X Y however does create an entirely new type which is physically identical to the original but logically unrelated (without any of the methods or anything).

Which is fine in the sense that it's what OP was looking for (completely independent types) but less so in that it doesn't forward any method, and it's not necessarily clear how you'd do that (type conversion, which looks really shitty when it involves pointers)

Re:I Want Off Mr. Golang's Wild Ride by whateveracct on Friday February 28, 2020 @01:16PM (#22444941)
Sorry I miswrote. I meant `type X Y` by "type alias" (terminology from other languages)

`type X Y` is still affected - you will 100% _not_ have more success :)

Proof (using JSON this time): https://play.golang.org/p/erfcSIe-Z7b

Re:I Want Off Mr. Golang's Wild Ride by masklinn on Friday February 28, 2020 @02:02PM (#22445334)
> `type X Y` is still affected - you will 100% _not_ have more success :)

type X Y neither inherits methods nor forwards anything (what struct embedding does), so you need to know about the protocol (which you're not told because it decides to just encode the bytes), and then you need to implement its methods on the newtype explicitly forwarding them to the underlying one.

TBF this is a pretty awful case as Go just goes and generates garbage without prompting.

Re:I Want Off Mr. Golang's Wild Ride by apta on Friday February 28, 2020 @03:34PM (#22446078)
golang's broken interface design also encourages hacks (which lead to difficult to track down bugs) like this: https://github.com/golang/go/issues/16474