Live data from Hacker News

I Want Off Mr. Golang's Wild Ride

fasterthanli.me

251–260 of 508 posts

Re: I Want Off Mr. Golang's Wild Ride

#251

Earlier quoted context omitted.

That said… I feel that Rust’s use of WTF-8 for OsString on Windows has resulted in some really nasty problems, especially since OsString doesn’t expose any useful methods for string manipulation. As far as I can tell, Rust’s approach fails to hide any of the complexity, and then adds the additional complexity of a new encoding and conversions on top. I can see that there’s some end goal of being able to work with OsS…

Isn't the point of OsString that it's essentially a faux-union type that is intended to be immediately converted to some concrete representation which /is/ richly manipulable?

The problem is that this is not good enough. It’s not uncommon to need to do a small amount of manipulation of OsString and there is no good way to do it.

In C++, it’s fairly easy. In Rust, it’s a damn nightmare.

In theory, in Rust, since OsString is basically Vec on the inside (like String), you could implement e.g. Path::has_extension in the same way as str::ends_with. However, anyone who has gone in and tried to implement this for OsString or Path has apparently gotten buried in the complexity and given up.

Re: I Want Off Mr. Golang's Wild Ride

#252
post #173

Earlier quoted context omitted.

name shadowing isn't the same as strong typing, you can do the same thing in rust today https://play.rust-lang.org/?version=stable&mode=debug&editio...

Reassignment isn't shadowing. See https://news.ycombinator.com/item?id=22444824 .

Steve's wrong. Python names can't be made mutable.

Re: I Want Off Mr. Golang's Wild Ride

#253
post #190
post #22

The author spent a lot of time dwelling on Window's filesystems, at which point many of the readers got bored and started commenting. There are actually a couple of excellent points in here, the majority of which relate to Go's tendency to just be silently completely wrong in its behaviors from time to time, and is absolutely packed with hidden gotchas.

And the other one is the tendency for Go's design to say "exceptions are allowed for me but not for thee". When I worked at Google I used other languages by some of the same authors and they showed the same design philosophy. Make things with an enforced simplicity, and where there were more special use cases that the language designer needed, they created escape hatches for themselves but not the language users.

And the other one is the tendency for Go's design to say "exceptions are allowed for me but not for thee".

Yes. Exceptions are kind of a pain, but the workarounds for not having them are worse. Passing back "result" types tends to lose the details of the problem before they are handled. Rust is on, what, their third error handling framework?

Exceptions have a bad reputation because C++ and Java botched them. You need an exception hierarchy, where you can catch exception types near the tree root and get all the children of that exception type. Otherwise, knowing exactly what exceptions can be raised in the stack becomes a huge headache. Python comes close to getting this right.

Incidentally, the "with" clause in Python is one of the few constructs which can unwind a nested exception properly. Resource Acquisition Is Initialization is fine; it's Resource Deletion Is Cleanup that has problems. Raising an exception in a destructor is not happy-making. It's easier in garbage-collected languages, which, of course, Go is. You have to be more careful about unwinding in non garbage collected languages, which was the usual problem in C++.

Re: I Want Off Mr. Golang's Wild Ride

#254
post #22

The author spent a lot of time dwelling on Window's filesystems, at which point many of the readers got bored and started commenting. There are actually a couple of excellent points in here, the majority of which relate to Go's tendency to just be silently completely wrong in its behaviors from time to time, and is absolutely packed with hidden gotchas.

> the majority of which relate to Go's tendency to just be silently completely wrong 100% right on. Go's handling of errors is often ridiculed for its verbosity and lack of thought, but the fact that Go makes it so easy to sweep errors under the rug has real and devastating consequences in the real world. Go programs are much less safe than programs written in Rust or Java for that reason.

Java just hides them in 40kb of logs that don't tell me anything.

I agree that golang makes it easy to lose errors but using Java as a better comparison is laughable in practical use.

Re: I Want Off Mr. Golang's Wild Ride

#255

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.…

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.

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

#256

Earlier quoted context omitted.

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

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.

It's still shitty and weird behavior. Not simple at all.

Re: I Want Off Mr. Golang's Wild Ride

#257
post #238
post #219

Earlier quoted context omitted.

"Go programs are much less safe than programs written in Rust or Java for that reason." This is plain wrong. ( Rust included )

Being unaware of an exception thrown by a function when calling it in Java will cause compilers to bark at you - while doing the same in go will work until it doesn't. I think this is even more insidious with changes in third party code over time though - did the package your gigantic product uses to validate that a phone number is in European time just add an error return value to a function that previously had none…

It doesn't make Go much less safer than Java. Go is a safe language.

Working long enough with Java I saw all the problems with exceptions and NPE and can tell you that those problems are less prominent with Go.

Re: I Want Off Mr. Golang's Wild Ride

#258
i cant help but feel Go is the new Javascript. Everyone wants to complain about how its semantics as a language do not align with their favorite programming paradigm. In this case, having complex, algebraic type-based abstractions that attempt to accurately reflect subtleties that are rarely important.

Yes, Go, as Javascript has unique failure cases and subtleties, but they are (as of 2020) very productive languages within their particular paradigms. That's not to say either language is beyond criticism, of course. But it's a little silly to think that a language that supports the 99.9% of writing a service well, but does the .1% badly as a tradeoff for simplicity is a fundamentally broken language because it doesn't share those aspirations. We might as well be complaining about the lack of pointer arithmetic in Python.

Re: I Want Off Mr. Golang's Wild Ride

#259

> Nine out of ten software engineers agree: it's a miracle anything works at all There was a beautiful rant about a decade ago called something like "everything's broken all the time and nobody cares." The gist of it is that all software is written by people. Anyone who's written software knows that it's usually riddled with hidden corner cases, unfortunate tradeoffs, rushed deadlines, etc. Software is also moving in…

I think you're thinking of Everything Is Broken by Quinn Norton https://medium.com/message/everything-is-broken-81e5f33a24e1

Re: I Want Off Mr. Golang's Wild Ride

#260
post #212

Earlier quoted context omitted.

Go doesn't ensure that you handle errors, if the function doesn't have a return value other than the error. The compiler will happily let you silently drop the result of os.Mkdir() on the floor.

I'm no Rust expert, but Rust doesn't enforce that either. There is no language that enforce error checking afaik.

All languages which uses Result or Either types...?
Post reply on HN