News for hackers. Stuff that matters.
Re:Why I love Go by s4vi0r on Tuesday December 05, 2017 @06:04PM (#15856950)
It's so strange seeing people who write these sorts of articles constantly praise Go's error handling. In what world is doing the whole if err != nil thing every 30-50 lines not ridiculous?

I get that goroutines are great, but that really seems to be all Go has going for it. The GC sucks, error handling feels like something from a bad language designed in the 70s, missing generics, math library is awful, Rob Pike being super opinionated, etc.

Re:Why I love Go by Xeoncross on Tuesday December 05, 2017 @06:20PM (#15857090)
> doing the whole if err != nil thing every 30-50 lines not ridiculous?

It's more like every 5 lines. I love it as every error is handled correctly and in scope. No error is left behind. Most languages I've used devolve into the GLOBAL MASTER DEFAULT HANDLE ALL ERRORS which is just gross.

Re:Why I love Go by lobster_johnson on Tuesday December 05, 2017 @07:34PM (#15857538)
In practice, scoping becomes an issue because "err" sneaks in everywhere.

For example, consider:

  foo, err := getFoo()
Now your scope has an "err" and you open yourself to logic errors such as:

  foo, err := getFoo()
  ... do stuff ...
  if errr := makeBug(); errr != nil {
    return err
  }
Spot the (heh) error? It's caused by ":=" allowing variables to be reassigned.

You can avoid this dangerous pollution, but it's super ugly:

  var foo *Foo
  if f, err := getFoo(); err == nil {
    foo = f
  } else {
    return err
  }
(You have to have the return in the second branch, otherwise "go vet" will complain. Sigh.)

I have lots of these, and they're not helped by the fact that Go has no type-level mechanism to guard against the misuse of multiple-return values. That is, in the above, either "foo" or "err" are usually set, and if "err" is set, it means "foo" isn't. But the type system doesn't prevent you from accidentally ignoring "err" and using "foo", or vice versus. This gets even worse if the func returns a (non-pointer) struct as its value.

The fact that Go allows shadowing (exacerbated by the convention of using "err" as every single error variable) and promotes the reuse of variables (e.g. the above ":=", or declaring "err" outside a loop) also means it's super easy to assign the wrong thing.

All of the above are my single biggest source of bugs during development. That, and how accidentally using nil/zero values, including the damnable nil map/slice cases.

"go vet" (whose shadowing check is disabled by default (!)) and the various linters only go some ways towards helping here. The errcheck linter (which you can enable through gometalinter) is absolutely essential.

Re:Why I love Go by Xeoncross on Wednesday December 06, 2017 @10:58AM (#15862056)
You almost always defined your variables. None of this `foo, err := getFoo()` nonsense.

Most functions return an error so err is already defined:

    func doIt(a, b) (result string, err error) { ... }
Then you are free to reuse err as needed.

        func doIt(a, b int) (result string, err error) {

		var x, y string

		x, err = doA(a)
		if err != nil {
			return
		}

		y, err = doB(b)
		if err != nil {
			return
		}

		result = x + y
		return
	}
Re:Why I love Go by lowmagnet on Tuesday December 05, 2017 @09:00PM (#15857912)

  var foo *Foo
  if foo, err := getFoo(); err == nil {
    return nil, err
  } 
  // foo is usable now
Re:Why I love Go by lobster_johnson on Tuesday December 05, 2017 @11:44PM (#15858589)
I suspect you don't know how := works.

  ./test.go:14:15: foo declared and not used
Re:Why I love Go by flip_rect_red on Wednesday December 06, 2017 @02:56AM (#15859356)
it appeared to be a typo, and as you suggest the compiler caught it

    var foo *Foo
    var err error
    if foo, err = getFoo(); err != nil {
        return nil, err
    } 
    //foo is usable now
Re:Why I love Go by lobster_johnson on Wednesday December 06, 2017 @03:22AM (#15859500)
That solves nothing. The point was that you pollute the scope with error variables, leading to dangerous logic errors that can be hard to spot. Your snippet is no better than:

  foo, err := getFoo()
  if err != nil {
    return nil, err
  }
"err" still ends up in the scope.
Re:Why I love Go by xenoncross on Tuesday December 05, 2017 @10:33PM (#15858248)
There are real problems, and not real problems. I'd classify this as a not real problem. How hard is it to name errors differently when it would be a real problem? A few keystrokes.. and BOOM! Problem solved.

I wonder what is the correlation between volume of complaining about minutia such as this compared to real life ability and level of accomplishment.

Re:Why I love Go by lobster_johnson on Tuesday December 05, 2017 @11:11PM (#15858410)
When you work with Go every day (which I've done for last two years or so), small problems become significant annoyances.

It's a decent language, but it's also a deeply flawed one. I could mention many other, bigger flaws, but this particular discussion was about errors.

Also, it's actually okay to debate minutia. Dismissing something as "not real problems" is, well, dismissive.

Re:Why I love Go by Xeoncross on Wednesday December 06, 2017 @10:53AM (#15862009)
What in the world? xenoncross?
Re:Why I love Go by hota_mazi on Tuesday December 05, 2017 @07:14PM (#15857439)
> I love it as every error is handled correctly and in scope.

Not in scope. Because you are forced to deal with the error right here right now, sometimes it's in scope and sometimes, you're simply not able to do anything with the error so you effectively mishandle it.

Exceptions allow you to handle the error where it actually makes the most sense.

Re:Why I love Go by embwbam on Tuesday December 05, 2017 @06:24PM (#15857127)
There are options between these two extremes. Haskell's Except monad is a great example. Or javascript promises. You can launch a bunch of actions in sequence and provide a single error handler for them. Each step doesn't have to worry about it, but neither is the error handling invisible and completely global.
Re:Why I love Go by haskellhater on Tuesday December 05, 2017 @07:37PM (#15857556)
Error handling in Haskell is, in practice, terrible. Not only do you constantly have to wrap and unwrap potential error values to unify different error types, you also have to deal with a dozen variants on Either and related typeclasses, none of which are used consistently across the ecosystem. And as if that wasn't bad enough, there are also actual throw-catch-style exceptions, which are not checked in anyway and, combined with laziness, can explode in your face at absolutely any time whatsoever. It's a big big mess. I stopped writing Haskell maybe a year ago, but at least back then getting GHC to print a stack trace when an exception wasn't caught was a major feat that involved recompiling every single one of your hundreds of dependencies with profiling flags. Guess how well that went most of the time.

Anyway, Go-style error handling's lack of any of these issues is what makes it attractive to me: it's simple, straightforward and get's the job done. Granted, with a bit more typing and the occasional bug that could have been avoided by not having to type the (almost) same three lines once again, but not having to jump through any of the hoops I keep encountering in more sophisticated languages is so, so worth it to me. I feel like Go stays out of my way, lets me focus more on actually getting things done than on dealing with the language's intricacies.

Re:Why I love Go by pcwalton on Tuesday December 05, 2017 @08:48PM (#15857859)
> Not only do you constantly have to wrap and unwrap potential error values to unify different error types

This is a legitimate issue, although in Haskell you can use one error type like Go does if you want to.

> And as if that wasn't bad enough, there are also actual throw-catch-style exceptions, which are not checked in anyway

This is also the case in Go (panics and recover).

> I stopped writing Haskell maybe a year ago, but at least back then getting GHC to print a stack trace when an exception wasn't caught was a major feat that involved recompiling every single one of your hundreds of dependencies with profiling flags.

This is also the case in Go. Errors do not retain anything about their state. You need to use a package like https://github.com/go-errors/errors, which has the exact same issue you describe with dependencies.

Re:Why I love Go by zaarn on Wednesday December 06, 2017 @03:22AM (#15859498)
>This is also the case in Go (panics and recover).

It is considered good style to not let a panic escape your library API unless something just went very severely wrong that the library could not possibly continue to function normally.

>This is also the case in Go. Errors do not retain anything about their state.

Errors are an interface, you can put any state inside it you want and I've frequently done so (retain line counts in parser or network data for example)

Re:Why I love Go by haskellhater on Wednesday December 06, 2017 @11:56AM (#15862624)
>> Not only do you constantly have to wrap and unwrap potential error values to >> unify different error types > > This is a legitimate issue, although in Haskell you can use one error type > like Go does if you want to.

SomeException is pretty much equivalent to Go's error, but it's not commonly returned by libraries and such so using it barely helps with the need to convert often. In addition all the types used by libraries as error values now need to have Exception implemented, which they don't. So, in practice, no, you cannot. Or rather, it wouldn't solve the core problem and create a new one.

>> And as if that wasn't bad enough, there are also actual throw/catch-style >> exceptions, which are not checked in anyway > > This is also the case in Go (panics and recover).

True, panic/recover exist, but in practice I find them to be more akin to setjmp/longjmp in C than throw/catch-style exceptions in other languages. Off the top of my head I can't recall a case where I had to recover from a panic that I didn't create in my own code (i.e. originated in a library call). Exceptions in Haskell and other languages on the other hand are usually all over the place (ok, usually not in pure code in Haskell) and I feel like I have to constantly keep them in mind to avoid letting one slip through the seams and then later having to track down where the hell that one came from.

>> I stopped writing Haskell maybe a year ago, but at least back then getting >> GHC to print a stack trace when an exception wasn't caught was a major feat >> that involved recompiling every single one of your hundreds of dependencies >> with profiling flags. > > This is also the case in Go. Errors do not retain anything about their state. > You need to use a package like https://github.com/go-errors/errors, which has > the exact same issue you describe with dependencies.

That's fair and indeed it would often be handy to know where an error came from. But since errors are just return values I don't really expect them to have a stack trace attached to them, just like I don't expect any other value to have that. It would still be neat for debugging sometimes, more so for errors than other values. I think there are some proposals for improving on this in Go 2. What really frustrated me about Haskell though was debugging throw/catch-style exceptions without a stack trace, because I basically had zero clues about where it came from and there were no clear paths to trace in the code. In Go on the other hand, errors don't just plop up from out of nowhere and panics, which can, print a nice stack trace when not recovered from.

Re:Why I love Go by alien_at_work on Wednesday December 06, 2017 @07:41AM (#15860629)
Haskell is an evolving language and the error story isn't entirely resolved yet. Personally, I like the MonadThrow stategy which gives the flexibility to the caller but the IO story gets in the way.

So yes, it can be messy when using other people's code because this is very much an unstable part of the language right now. I still prefer that over the worst possible strategy (what Go picked) being effectively baked in.

Re:Why I love Go by acjohnson55 on Tuesday December 05, 2017 @06:58PM (#15857360)
Yep. For my money, the war is over, and the monad won. I shouldn't say the m-word, as it turns people off. But that's the unifying pattern.

Javascript messed it up a little bit with promises, because it's so easy to swallow errors. IMO, they should have made it so that unhandled promise rejections throw by default at the next turn of the event loop, with a method that could be called to opt out individual promises.

Re:Why I love Go by girvo on Tuesday December 05, 2017 @08:58PM (#15857902)
They have, sort-of!

At least, V8 did IIRC. I use Creed[0] myself, which using it's `shim()` function gives you the same behaviour. It's quite lovely.

[0] http://blog.briancavalier.com/creed/

Re:Why I love Go by ardi93 on Tuesday December 05, 2017 @07:30PM (#15857519)
> No error is left behind

I don't think so. You can choose to ignore the error (I know it's bad practice), but it's allowed. And sometimes you don't know what to do with the error

Re:Why I love Go by aninhumer on Wednesday December 06, 2017 @06:17AM (#15860240)
Handling errors as values is great, but making that value a product type rather than a sum type is not good design. It means you have to return a result even when you have an error, and so nothing enforces that the user actually handles the error properly.
Re:Why I love Go by millstone on Tuesday December 05, 2017 @10:59PM (#15858359)
Go errors are routinely ignored. Even Hello World ignores the error return.

https://gobyexample.com/hello-world

Re:Why I love Go by thewhitetulip on Wednesday December 06, 2017 @02:33AM (#15859264)
No. That is incorrect. Errors are to be handled by the programmer and every book I read says "We are ignoring errors here for the sake of simplicity, you are strongly advised not to ignore them".

I have said so in the intro textbook I wrote.

Re:Why I love Go by junke on Wednesday December 06, 2017 @04:38AM (#15859801)
Error handling is what happen after you discover there was an error. In Go, "checking" for errors may be skipped (and people make mistake, even True Programmers), in which case they are handled just as if they were ignored.

Even if the error can be ignored for fmt.Println, it is not clear from the example whether it was even taken into account or not. The following could be required:

    _ := fmt.Println("hello world")
That means that the function call can return an error, and thus you have to use the return value, but the programmer decided to ignore it. Contrast it with:

    fmt.Println("hello world")
Did the programmer know there was possibly an error? What happens if there is an error (not specifically for this example, but in general), and you don't check for it? then it is ignored.

In another language, the same line could be the source of an error; but only error handling depends on the programmer, not error checking. Moreover, the default handling strategy is to abort execution. Actually ignoring errors requires more work.

And errcheck is apparently no silver bullet: https://github.com/golang/go/issues/20148

Re:Why I love Go by pjmlp on Wednesday December 06, 2017 @02:08AM (#15859166)
That is a fallacy because I have seen Go code with _ everywhere , thus not handling errors at all.
Re:Why I love Go by zaarn on Wednesday December 06, 2017 @03:24AM (#15859508)
Most linters that concern themselves with errors will complain about this and I would not accept any code that does this beyond tests.

Go allows you to do certain things but it's not a fallacy because it's something that's allowed but not necessarily tolerated by what most consider "good Go coding standards"

Re:Why I love Go by pjmlp on Wednesday December 06, 2017 @04:34AM (#15859789)
My consulting experience has shown that beyond startups, or a few Fortune 500 companies like Google and FB, linters and code reviews are seldom done, unless we are speaking about safety critical domains like aeronautics, autos, train control systems,medical devices....
Re:Why I love Go by zaarn on Wednesday December 06, 2017 @04:44AM (#15859828)
So because a lot of people don't use best practises that means the language in which these are to be used is worse off?

It strikes me a bit like saying "because most people don't wear seatbelts, cars are unsafe because you may get ejected out of the cockpit in a crash". Wear a seatbelt and use linters, I'm not going to excuse the malpractices of the larger industry.

Re:Why I love Go by pjmlp on Wednesday December 06, 2017 @05:34AM (#15860036)
No, it follows junke answer.

Optional external tools, are exactly that, optional.

Lint was created for C in 1979, a minority used it or its commercial versions like Gimpel, until clang was introduced with static analysis built into the compiler.

Anything that isn't enforced by the language, tends to be ignored, hence why we need good defaults that make workarounds a big pain.

Re:Why I love Go by junke on Wednesday December 06, 2017 @05:08AM (#15859927)
That means that you better have safe defaults in a language, rather that opt-in linters.
Re:Why I love Go by zaarn on Wednesday December 06, 2017 @05:16AM (#15859964)
More safe defaults also means I have to think more about escape hatches. Sometimes ignoring an error is the intended way of operation, although rare. Same goes for some other parts of the go coding standards. Sometimes you need to violate them and having to first use some escape hatch like Rust's unsafe is annoying.

I'd rather just keep track of linter complaints.

Re:Why I love Go by junke on Wednesday December 06, 2017 @06:13AM (#15860221)
Yes, ignoring an exception is an explicit move when the default mechanism is to abort execution. Since it is rare, I don't see a problem.

> I'd rather just keep track of linter complaints.

Do you dislike "unused variables" being compilation errors, too?

Re:Why I love Go by zaarn on Wednesday December 06, 2017 @06:43AM (#15860365)
Not really. It has changed my coding style so I now only add variables when needed, even in languages like JS. I only get the "unused variable" error about once a month.
Re:Why I love Go by taneq on Tuesday December 05, 2017 @07:22PM (#15857479)
ON ERROR RESUME NEXT
Re:Why I love Go by mmargerum on Wednesday December 06, 2017 @07:35AM (#15860602)
Explicit error handling in go is wonderful. I consider it a feature
Re:Why I love Go by 013a on Tuesday December 05, 2017 @07:46PM (#15857606)
I really think error handling could be solved by adding some simple syntactic sugar.

For example: "if err" being compiled directly to "if err != nil" would be a quick win.

Second more complex idea: add a new keyword like "res := throw MyFunction()", being allowed if "MyFunction()" returns an "error" as its last argument and the calling function returns an "error" as its last argument, simply return the zero value or named return value of any other return values + the error if there is one, otherwise continue.

Point being, the core of Go is really good. When I come across a command line tool written in Go, my first thought is "fuck yeah, this is going to be so easy to install", versus something like Python which is a bitch unless the developers have taken the time to brew it or something. Countless planet-scale infrastructure tools have been written in it; Kubernetes and Docker to start. I can name a dozen startups, both large and pre-seed, which use it with resounding success.

Yes, it has warts. Every language has warts. Go is just "different" because it tries to be simple. Nearly no other language in the world has "simplicity" as one of its core values, and a lot of people don't fully respect what that means.

Re:Why I love Go by TheDong on Tuesday December 05, 2017 @08:21PM (#15857755)
None of that helps with the real problem of golang errors.

The real problem with go's errors is complex and significant.

There's no Either/Result type so the multiple return doesn't actually tell you that you get a zero value when there's an error (and in fact there are functions in the stdlib that do this).

There's no good way to check whether an error is a given thing because error chaining isn't built in and errors rarely are typed as sum-type-enums as they are in rust or other decent functional languages. For example, `os.IsNotExist(err)` will not work for a caller if I did `return fmt.Errorf("error opening file: %v", err)` in a function.

The stdlib encourage a dozen really bad methods of doing error handling; there's `io.EOF` (which is a mutable variable btw). There's PathError. There's os.IsNotExist. There's random panics in some functions. There's nil returns with no further info.

The stdlib has multiple examples of 3 or 4 different error handling styles, and they're all horrific because they don't chain and don't allow for exhaustive matching.

Go may be good compared to C or other languages that were designed way back when. In modern times, go is a massive step backwards with its incredibly underwhelming type system, absolutely asinine community, lack of good abstractions, and so on.

Re:Why I love Go by alien_at_work on Wednesday December 06, 2017 @07:46AM (#15860654)
Exactly right. If all computer languages were created anonymously, Go would be less popular than BF.
Re:Why I love Go by geodel on Tuesday December 05, 2017 @07:09PM (#15857412)
Nothing ridiculous about it. I work on a Java code base where there is try catch every 4-5 lines. The application is working fine and nobody is unduly worried about fine taste in exception handling. If application were in Go it would have err != nil every few line that would also be fine for us.

With all the things that you mention Go does not offer helps it keep simple. It has already proven much useful for many of of my projects where a 'better' language would fail for variety of reasons.

Re:Why I love Go by hota_mazi on Tuesday December 05, 2017 @07:13PM (#15857430)
> I work on a Java code base where there is try catch every 4-5 lines.

There is a huge difference.

The Java code you are reading is caused by bad programmers who are not using exception handling correctly. Proper exception use means sometimes catching and sometimes ignoring the exception and declaring it in your `throws` clause.

In Go, testing against `nil` every twenty lines is not only common, it's the ONLY way to write robust code. You simply don't have a choice.

Re:Why I love Go by geodel on Tuesday December 05, 2017 @07:30PM (#15857517)
Considering so many projects in last 10 years where code was not even formatted even though it was one command away in IDE, ridiculous variable names, useless comments like 'method getA() returns A" I am not sure it is result of bad programmers or just natural state of IT industry. Java succeeds despite lot of bad code mean immense hard work on performance/ libs side by JDK teams.

I think same is going to be true for Go. I have written few projects in Go and they have produced much more value than time taken to write them.

At the end of day companies I worked for prefer mediocre code that is written and used vs excellent code in brilliant programing language that was never completed.

Re:Why I love Go by e3b0c on Wednesday December 06, 2017 @12:41AM (#15858816)
Interestingly it makes me a better programmer after being used to the Go style. Now I don't allow unused headers/variables in my C/C++ code and feel natural to check every return error. 'Optional' warnings don't happen anymore either since -Werror feels familiar. Overall my C/C++ code becomes more reliable and easier to debug.
Re:Why I love Go by juhanima on Tuesday December 05, 2017 @07:40PM (#15857579)
No, it is not ridiculous, it is meticulous. That's one style and approach in programming and not without merits.

I personally like exceptions, as they enable focusing into what's supposed to happen instead of what all could go wrong. And the abstraction power that comes with this approach.

But I wouldn't rush to say I'm right and the meticulous party is wrong. There are many instruments in the orchestra. In the end all that matters is the skill of the player.

Re:Why I love Go by TheDong on Tuesday December 05, 2017 @08:27PM (#15857782)
Exceptions are a strawman.

I don't like exceptions. Go's error handling is still ridiculous.

It doesn't have sum-types, it has the incredibly stupid interface/struct nil punning so you must return an interface and type-assert down, it doesn't have a tuple object being returned but actually multiple return which is a semi-broken thing, it doesn't have an either/result type or an optional type to express mutual-exclusivity / optionality....

Yeah, the whole thing is disgustingly bad. That doesn't mean I prefer exceptions.

I do prefer meticulous "errors as value" error handling. Go's implementation is the worst implementation of that because the type system doesn't support various features that make handling error values better.

Re:Why I love Go by alien_at_work on Wednesday December 06, 2017 @07:59AM (#15860728)
Yes, it's amazing that a language made when Go was is basically a version 1.5 of languages made 40 years ago. C had the worst possible error handling and Go has swooped in to take the second spot.

The very best error handling I know of is in CLOS. Instead of exceptions, they have "conditions". A condition is signaled like an exception but with a big difference described below. The thing about errors is, the code that detects the error can never know how to deal with that error. If it did, then it wouldn't be an error it would be a case within that function. However, that code may know ways the error could be dealt with, it's just not in a position to choose. So what conditions do is, you can define a condition and so called "restarts" along with that condition. What the restart does is say "here is a way I could handle this error" and code higher up the stack has the option to (1) use the restart, (2) define additional restarts on that condition or let the condition propogate upwards. The condition signalling does not necassarily unwind the stack: if you choose a restart, the code continues in the stack that restart was defined.

So this means every part in the stack that knows how a condition could be recovered from can provide the option but it is left to code higher in the stack to chose the actual strategy. This is superior to the exception strategy of unwinding the stack until you find a handler because sometimes you really want the code to continue execution where it is.

But, of course, such a system is really expensive to implement. If you can't have that my preference is the Haskell style of using a sum type where errors can happen but writing as much of your code as possible with any error conditions prohibited by the type system.

Re:Why I love Go by steveklabnik on Wednesday December 06, 2017 @08:23AM (#15860860)
Fun fact, Rust had conditions a very long time ago https://doc.rust-lang.org/0.9/guide-conditions.html

Nobody used them, so we removed them.

Re:Why I love Go by flavio81 on Wednesday December 06, 2017 @08:42AM (#15860956)
Well, that's really bad, because I think that things should be implemented in the best way possible. "Nobody used them", yeah, probably because no other language (apart from CL) had it, so nobody knew how to leverage them. But leave it in place and at some point in future time, some blogger would write a nice article on using them in Rust and developers would catch up in this cool feature.

I develop in Common Lisp and conditions&restarts are so much superior to the other error handling paradigms i've seen, that it's not fun being left without them.

Re:Why I love Go by steveklabnik on Wednesday December 06, 2017 @09:15AM (#15861145)
At the time, those docs were the error handling documentation, so people did know they existed. They still weren't used anyway.
Re:Why I love Go by alien_at_work on Wednesday December 06, 2017 @10:20AM (#15861670)
I think the point is that sometimes showing documentation that something exists isn't enough for everyone to "get it". Sometimes you need some kind of technology evangelist to show something really cool they did with a feature for the creative process to begin on a larger scale.

Out of curiousity, if this was just a macro and no one was using it, what would have been the harm in just leaving them in? Is this a part of the language that changes so much it made maintainance a pain?

Re:Why I love Go by steveklabnik on Wednesday December 06, 2017 @10:49AM (#15861973)
Macros in Rust are global, insta-stable, and have no namespacing. This means any macro we put in std means you cannot define a macro in any Rust program with that same name. This is one of the reasons we've been working on a new macro system, to fix these kinds of issues.

"Just leave it in" isn't a good justification for a feature. We'd then require that every implementation of Rust ever, forever, implements this too. Being in std is a high bar.

Beyond that, there are a host of other reasons: https://github.com/rust-lang/rust/commit/454882dcb7fdb03867d...

Re:Why I love Go by draegtun on Friday December 08, 2017 @12:08PM (#15880133)
Perl6 & Smalltalk also have them (conditions&restarts).

And i've seen modules to add condition systems to perl5, Ruby & Clojure. But these are kinda of hacks so the more languages that have it baked-in the better!

Re:Why I love Go by flavio81 on Saturday December 09, 2017 @09:36AM (#15885948)
Thanks, I stand corrected. It seems Perl has everything!
Re:Why I love Go by mappu on Tuesday December 05, 2017 @06:30PM (#15857178)
What don't you like about Go's GC?

Compared to Hotspot, it doesn't STW; it makes a different throughput/latency tradeoff that is more suited for its application domain; and it's actually needed a lot less often because the compiler can put many objects on the stack.

A generational collector is currently under development (but won't be in 1.10).

Re:Why I love Go by pcwalton on Tuesday December 05, 2017 @08:54PM (#15857887)
> Compared to Hotspot, it doesn't STW

Stop the world typically happens during compaction phases. Golang "solves" this by just not doing any compaction. That's certainly a big tradeoff.

> it makes a different throughput/latency tradeoff that is more suited for its application domain

I don't really agree. While low latency is nice for consistency, low throughput means you may have to buy more servers to handle your load. That isn't always a win.

> and it's actually needed a lot less often because the compiler can put many objects on the stack

HotSpot can, and does, do this too!

> A generational collector is currently under development (but won't be in 1.10).

Does it? Do you have a link?

I haven't found any information about this.

Re:Why I love Go by remus on Wednesday December 06, 2017 @06:50AM (#15860406)
>> A generational collector is currently under development (but won't be in 1.10).

> Does it? Do you have a link?

https://docs.google.com/document/d/1gCsFxXamW8RRvOe5hECz98Ft...

This is the original proposal, although I believe it has evolved significantly during development (in testing some of the proposed ideas didn't pan out as expected).

Re:Why I love Go by pcwalton on Wednesday December 06, 2017 @11:38AM (#15862449)
That's not really a generational collector, and it doesn't achieve the main benefit of one: bump allocation in the nursery.
Re:Why I love Go by nurettin on Wednesday December 06, 2017 @12:29AM (#15858770)
Golang solves memory fragmentation by allocating more intelligently. I assume you know about tcmalloc?
Re:Why I love Go by tychver on Wednesday December 06, 2017 @09:15AM (#15861149)
Go merely adopts a different strategy which quietly fucks you in a different set of circumstances: https://news.ycombinator.com/item?id=15823683
Re:Why I love Go by pcwalton on Wednesday December 06, 2017 @11:38AM (#15862453)
HotSpot's memory fragmentation solution is superior, because it has a semispace copying collector in the nursery.
Re:Why I love Go by twic on Tuesday December 05, 2017 @07:22PM (#15857480)
As a Java aficionado, i have a lot of respect for Go's GC. It may not be as sophisticated as the JVM options, but it has a laserlike focus on low pause time, and does a phenomenal job of delivering it, given how much less development effort has gone into it. It's really lit a fire under the JVM developers, at Oracle and Red Hat, to improve the realtime collectors in the JVM.

Not IBM or Azul, though, their JVMs already have kickass realtime collectors.

Re:Why I love Go by openasocket on Tuesday December 05, 2017 @06:48PM (#15857295)
Hotspot has several GC algorithms available, FYI. And the term "stop the world" is misleading, it doesn't fully capture the nuance of garbage collection. Any GC algorithm that does compaction will require some sort of blocking. You can do compaction incrementally, so you only lock small sections of the heap at a time, but that would still be considered "stop the world" despite being orders of magnitude faster than the naive case.

Go GC gets to make the claim that it doesn't "stop the world" because it doesn't do heap compaction. Which will become a major problem when dealing with large in-memory data structures or certain usage patterns.

And the fact that they still don't have a generational collector is concerning.

Re:Why I love Go by tychver on Wednesday December 06, 2017 @09:22AM (#15861192)
Erlang has a really nice solution here by using a separate heap per Erland "process", and because they're owned by that process, can do a copying/compacting GC without having to take any kind of locking. Ruby's Guilds could adopt a similar idea and avoid STW GC there too.
Re:Why I love Go by openasocket on Wednesday December 06, 2017 @12:02PM (#15862682)
Again, the term "stop the world" is misleading, there are a variety of compaction strategies that greatly minimize locking. There are even realtime GC implementations for the JVM.

Erlang's solution is interesting, but remember in Erlang processes can't share memory, they only have message passing. So you never have to worry about multiple threads writing to the same data structure at once, which is what makes compaction hard.

Re:Why I love Go by tychver on Wednesday December 06, 2017 @05:30PM (#15865675)
Sure they can. There’s a separate shared heap which uses atomic ref counting.
Re:Why I love Go by julenx on Wednesday December 06, 2017 @05:27AM (#15860010)
In a memory constrained environment, we recently noticed the throughput/latency tradeoff being made by the GC, but having to say that this behavior was not obvious in the first place and we had to dive into the source code to understand things better (which is a good benefit of go being open source, as already stated in the article).

The bottom line is that the scavenger will allow the OS to claim free memory only at least 5 minutes after it was GC'ed. For us the solution was to "force" releasing the free memory to the OS [1], and even since then things have been much smoother in the context of our particular app.

On this topic, there's an open issue [2] to look at making the scavenger more prompt and aggressive.

[1] https://medium.com/samsara-engineering/running-go-on-low-mem... [2] https://github.com/golang/go/issues/16930

Re:Why I love Go by valuearb on Tuesday December 05, 2017 @07:34PM (#15857541)
If you aren't checking errors more than once every 30 lines you probably aren't doing it right.