Hacker News new | past | comments | ask | show | jobs | submit login

I really want to love this language, a fast and simple garbage collected lang, but feel like they missed the spot a little. I just wish they did something different with error handling / nil, doesn't feel right for the language. Also whats up with stuff like unused imports being such a big deal?



I keep count in my own code of the number of bugs Go's "damnable use requirement" has caught for me, and I'm now up to 5. It's not a big number, but they were real bugs that would have annoyed the shit out of me if they'd made it into shipping code. I think this is one of the polarizing decisions Go made that is going to turn out to be universal orthodoxy 10 years from now.

I think error handling is the thing about Go that people get most wrong. I believe that what's happened is that Go expected its users to be people fleeing C++ (they definitely got that one wrong), and instead they got a flood of Python and Java developers. Systems programming is error programming. Hiding and abstracting errors in systems code isn't a win; it's a handicap. Fiddly decisions about errors is the whole ballgame. But that's not the case in application code (EAFP!) and Go has been beset by that countervailing sentiment ever since.

That's not to say Go's got error handling perfect; it would be better with matching. But no mainstream language gets errors perfect. What unifies the strong systems languages is that they enable the overt programming of errors.


The biggest problem with the error handling is that it's not composable. It's better than unchecked exceptions, but that's not saying much.

The second problem is nil, use of which is common and doesn't enforce error handling.


I find it inconstant to be so pedantic about unused vars/imports to avoid bugs, but then leave error handling to what it is.


I think solid error handling is the difference between production and prototype code, even in applications. They may not have to be handled in the same way as in systems programming, but they still have to be handled in a careful, consistent, disciplined way.


> I keep count in my own code of the number of bugs Go's "damnable use requirement" has caught for me, and I'm now up to 5.

Are you saying that you’ve had 5 bugs caused by unnecessary imports?


I'm saying I've had that stupid import error pop up in my face 5 times and changed my code as a result, rather than the imports, because it surfaced an error.


Shouldn't it be a warning, though? You'll still notice it, but you aren't forced to deal with the problem immediately.


I'm not saying it caught syntax errors. I'm saying it caught actual bugs in my code. I don't want to be allowed to blow those off.


>I'm saying it caught actual bugs in my code.

It did so 5 times, versus how many times it gave a false positive where you just had to delete the import or underscore the variable?

Warnings are intended precisely for this type of "hey, you probably made a mistake here". Errors should imo be reserved for cases where the compiler is more or less sure you are wrong.

Rust has probably the biggest possible focus on "making sure only correct programs compile", and rustc does not error on an unused variable or import; it gives a warning. Precisely because it does not know if it is a bug, or just, I don't know, "commenting out the code that uses it to try something".

Also, in the case of an unused variable, you CAN blow it off, by using _. In fact, this makes it far easier to forget about it later compared to a warning that can be silenced in the same way, because if it's a warning you'll only do it if you're actually sure, while with an error you might do it even if you're less certain, because it's absolutely necessary.


Together with that any reasonable codebase denies any warnings from the compiler, Clippy or changes from running Rustfmt when running CI. Which is pretty much equal to Go best practice, using something like Golangci-lint instead.

Although, I guess this is the difference between being 13 years old and 7. For Rust easily accessible CI has always existed, for Go at the time of launch it took effort setting it up. Therefore best practices were pushed into the compiler to the detriment of the users, giving the same benefit trading effort writing the code.


My biggest complaint in go is "Defaults are useful" logic. I have seen numerous serious production incidents due to simple uninitialized variables. The only workaround is to use a function for all initialization but because that is more verbose it is often not done, and you lose the "keyword arguments" of struct literals.

There are other footguns like the unpredictable by-reference behaviour of slices and the printf functions corrupting your output if you make a type error but they are much less severe than the misguided idea that implicit default values are useful.


What’s about unused imports? Imports usually added/removed automatically by editor.


> Also whats up with stuff like unused imports being such a big deal?

https://go.dev/doc/faq#unused_variables_and_imports




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: