Live data from Hacker News

I Love Go; I Hate Go

dtrace.org

271–280 of 329 posts

Re: I Love Go; I Hate Go

#271
post #201

I think a persons opinion on Go really depends on where you're coming from and what tooling they are used to. As a PHP/Node/Ruby dev I find Go does everything PHP/Node/Ruby does, faster, and more reliably due to static typing. Often more verbosely though. I've simply never wanted for the things he asks as I've never had them. It's all in the expectations is my point.

It's telling that the most sophisticated type system you've dealt with is Ruby, though. I think that if you spent some time working in OCaml/Nim/Rust/D/C# you'd learn a lot which would cause you to be a lot less impressed with Go.

Re: I Love Go; I Hate Go

#272

Earlier quoted context omitted.

This post is yet another reinforcement of my assertion that the people who like Go only like it because they have no idea what has happened in programming languages for the last few decades. Case in point: > It brings back the virtues of the Wirth computer language family back into modern times, as with strict type checking and the module system. Strict type checking? Have you used any other languages besides C ? Go'…

Why is the type system a joke (genuine question)?

It provides zero abstraction, which is especially painful when handling errors. In Go you basically _have_ to handle the error right when you receive it, there is no way of usefully combining or composing it. Also error handling itself is very verbose and can't be abstracted over.

In other languages you can compose errors just as regular values, which allows you to handle the errors at the place where you have all the information to deal with it.

Not only that, the types represent the structure of the computation you ran.

For example, your type is Future[Option[List[Person]]] and just by looking at the return types of the things you called, you can tell exactly _where_ an issue occurred and how to handle it:

Your value is a Success(None)? -> The method inside your asynchronous computation that returned Option[List] failed!

Just to note, Future[Option[List[Person]]] is not some made-up example, it could be a real-world query against the database–for instance "do we know the friends of user X"?

  - Future – we run it async
  - Option – we might not know it
  - List   – his friends
This let's us very neatly tell apart things like

  - Failure – "the database response from the database timed out" 
  - Success(None) – "we have no idea about user X' friends"
  - Success(Some(Nil)) – "X has no friends"
  - Success(Some(List(...))) – "here are X' friends"
(And the compiler will make sure that you handle all possibilities)

In Go the closest pattern would likely be to extract the string from the error value and compare it to error strings you recognize. An alternative would be to define a special single-purpose data type specially for each type including all combinators, as Go would not be able to express any commonality between Future[Option[List[Person]]] and Future[Option[List[Pet]]]. You would need to define 4 new data types and all operations anew.

Re: I Love Go; I Hate Go

#273
post #191

Earlier quoted context omitted.

Well, the latency is capped at 10 ms, the STW phases will stop at that limit. So that guarantee can be kept as long as your memory allocation throughput is low enough so as not to trigger a GC run more than 20 times a second. Which is pretty good. There aren't that many GC implementations in production that will give you a guarantee of the same or similar quality.

Can you point me to an authoritative source that explains what exactly is guaranteed under what assumptions and what is done on a best effort basis only?

The authoritative source is the Go source code. Read it, it's relatively easy to understand, and fairly obvious that the STW mark termination phase goroutine (like any other goroutine) will be preempted after forcePreemptNS (which is 10ms), and if that happens even though it hasn't finished its work, it transitions to a concurrent task, and resumes later.

If you're interested in the finer details, I'm sure the GC talk at golangUK later this month will discuss them all, and the slides and/or videos will eventually land here on Hacker News.

Re: I Love Go; I Hate Go

#274

Earlier quoted context omitted.

> Sometimes I like to have a fully statically typechecked program. Wait, I thought we were talking about situations where Go was appropriate. What do you use when you want a fully statically typechecked program?

Please don't do this. You obviously disagree that Go is a language which provides full static typechecking. Please instead just state that disagreement, rather than feign confusion. It leads to much better discussions.

Why do Go advocates never have any technical response to facts they dislike, but always respond with complaints about the tone in which the fact was voiced?

Re: I Love Go; I Hate Go

#275
post #232
post #171

Earlier quoted context omitted.

Sometimes I like to have a fully statically typechecked program. You can do that in Lisp, its easier in Go. Also, it directly produces statically linked executables. You can do a lot of this in SBCL, it also produces executables, has type checking etc. But for some of this, you have to wrestle a bit with the Lisp system. The Common Lisp numeric tower is great - until you want to write low level programs where you jus…

I guess I don't write the same kind of tools as you, I never need word sized integers. Generally, I define the types according to the problem domain and don't require a specific bit layout. A different case arises when you exchange data through a given protocol, but then you don't do computation with it, just encode/decode.

Word sized integers are fast to compute. So as long as your problem can be expressed with them, it is the fastest way to perform math. When using Common Lisp, I have flexible sized integer numbers, which is nice to have, but the performance penalty can be sometimes too high.

Re: I Love Go; I Hate Go

#276
post #181
post #50

Earlier quoted context omitted.

"But it […] has saved me from bugs repeatedly; I more and more notice the bugs it's protecting me from as I keep coding in the language […] most Go programmers use "goimports" to work around the annoyance. I have my Emacs configured to use it automatically. I never even think about imports anymore." If you don't think of imports anymore, how can they save you from bugs? (I do (somewhat) understand the "more important…

The use requirement for variables saves him from bugs, goimports fixes the problem with required use of packages. It's separate. The requirement that packages aren't used isn't to prevent bugs, it's to prevent packages from claiming spurious dependencies that you're then too afraid to remove. Or, in the case of a static language like Go, don't want to take the time to remove one-by-one and see if the compilation brea…

"It's separate"

I don't think I misquoted the OP. He said "A and B help me with C" and I questioned how A could help with C, given the other claim that the OP doesn't pay any attention to A anymore.

"Or, in the case of a static language like Go, don't want to take the time to remove one-by-one and see if the compilation breaks"

That is a problem with perl, a language whose 'grammar' is about as free-form as it gets (aside: iOS is funny at autocorrecting programming language names: cobol => cool, perl => peril or pearl, depending on context), but not with go. The compiler can generate errors for unused imports; it easily could generate warnings instead.

I like clean code, but I also like it if a quick experiment doesn't require extra tooling to remove imports to make things compile, more so if it is not guaranteed that undoing such changes can be automated (adding imports isn't 100% reliable; if it were, why have import statements at all?)

In summary: Go is too opiniated here for me.

Also, this requirement effectively rules out ever using go in a repl. I think that is a minus for modern programming languages.

Re: I Love Go; I Hate Go

#277
Those are really small annoyances compared to everything else in Go. I don't mind Go being opinionated, everything is like that anyway and it's kind of nice in some ways. But don't mistake opinionatedness with misdesigned poor quality libraries and experimental ideas.

Take net package for example, it's not opinionated, it's just completely broken and misdesigned. There is so much mess with even the most basic things, like timeouts and cancellations [1][2] that it's almost impossible not to fuck up somewhere.

This is because the whole net library is synchronous and pushed onto experimental ideas of goroutines and channels. Instead of having an actual event loop underneath with timers, signals and everything and use asynchronous writers and readers they just poll fds and wake goroutines when fds are ready, forcing themselves to deal with typical multithreaded concurrency hell.

[1] https://blog.cloudflare.com/the-complete-guide-to-golang-net... [2] https://github.com/golang/go/issues/16100

Re: I Love Go; I Hate Go

#278
post #261

Earlier quoted context omitted.

Define "feature". Go thinks fast compile time is a feature. How fast is your Algol 68 compiler on a ten million line code base?

Fast enough for a 60's computer, imagine nowadays. But if you want numbers, Turbo Pascal 5.5 was doing 34,000 lines/minute[1] on MS-DOS back in 1989. [1] http://edn.embarcadero.com/article/20803

Turbo Pascal isn't Algol 68. A PC in 1989 isn't a B5000. But even accepting the example, 34,000 lines/minute gets you a compile that takes 294 minutes, or just under 5 hours. That's... not very good.

Of course faster hardware is part of the answer, but I suspect that it doesn't cover nearly all the ground between Turbo Pascal's compile time and Go's.

Re: I Love Go; I Hate Go

#279
post #263

Earlier quoted context omitted.

> > Differing use cases lend cause to different tooling. > What? Different needs, different languages. I write 100-line scripts in Perl that rip apart text files and extract the bits I want. I don't write 100,000 line embedded systems in Perl.

What about different needs among the users of a same language?

Any language satisfies some needs well (hopefully), and some needs less well, and some other needs badly. Different languages have different sets of needs that they satisfy well.

So, if you're complaining that a language doesn't satisfy a need well, then go find one that satisfies it better. Use that instead.

Re: I Love Go; I Hate Go

#280
post #260

Earlier quoted context omitted.

The unused variables are the things that can really cause bugs in your code. It's annoying, and I share your annoyance, but I have also sighed to myself and said "shit, I'm glad Go caught that" after noticing really bad bugs that the error flagged.

That's why unused variables should be reported. What people are arguing about is errors vs. warnings. > things that can really cause bugs "can" means that they don't always cause bugs: other compilers treat such uncertainties as warnings because the human looking at the screen is the one who is in charge. Go allows you to compile code which does not respect "go fmt", why? aren't you afraid of committing working code…

As someone else pointed across the thread, the error eliminates these bugs, not only in your code but, effectively, in all the libraries you import. It takes effort to retain those bugs.

That has significant value, and is why I've conclude Go's choice here was the right one, despite the annoyances it causes.

I like gofmt, but I don't really care whether the compiler enforces it. It's unlikely to catch bugs.

Post reply on HN