Golang be like - lemm.ee

As your future colleague wondering what the hell that variable is for, thanks Go.
A quick “find all references” will point out it’s not used and can be deleted if it accidentally gets checked in but ideally, you have systems in place to not let it get checked into the main branch in the first place.
Yeah that should be looked for in a CI line check, not a compilation requirement
Yeah any compiler should support environments or confit files. Our CI would never with without –env “stage”
You mean a system like the compiler
Or a linter. Or code reviews. Or anything else. The nice thing is that if the compiler doesn’t demand something. The compiler should have the option to do it. The option could even be defaulted on. Afaik there is no way in Golang to disable that error (this is the line that does it: github.com/golang/go/blob/…/stmt.go#L67-L69). like --no-pedantics or such. Golang’s compiler openly refuses to give engineers more choices in what they think is the best system to handle it.
go/src/go/types/stmt.go at 04fb929a5b7991ed0945d05ab8015c1721958d82 · golang/go

The Go programming language. Contribute to golang/go development by creating an account on GitHub.

GitHub
Who needs an option to leave unused variables around the code base? Lazybones?
You’ve literally never commented out a line or two but left the variable declaration while debugging?

Changing it will bring down the entire system.

We’ve spent ten million dollars and do not know why.

Isnt the syntax highlighting it as mever used?

So why would they wonder?

If it is a pure value, I’d assume yes, but if it is tied to a side effect (E.g. write its value to a file), then it would be not used but still could break your app if removed.

I’m not familiar with rust language specifically, but generally that’s what could happen

If only there was some way the compiler could detect unused variable declarations, and may be emit some sort of “warning”, which would be sort of like an “error”, but wouldn’t interrupt the build, and could be treated as an error in CI pipelines

Let’s not pretend people acknowledge warnings, though. It’s a popular meme that projects will have hundreds of warnings and that devs will ignore them all.

There’s a perfectly valid use case for opinionated languages that don’t let you get away with that. It’s also similar to how go has gofmt to enforce a consistent formatting.

You can, if you want, opt into warnings causing your build to fail. This is commonly done in larger projects. If your merge requests builds with warnings, it does not get merged.

In other words, it’s not a bad idea to want to flag unused variables and prevent them from ending up in source control. It’s a bad idea for the compiler to also pretend it’s a linter, and for this behaviour to be forced on, which ironically breaks the Unix philosophy principle of doing one thing and doing it well.

Mind you, this is an extremely minor pain point, but frankly as with most Go design choices there is a better way to solve the problem.

Some people simply ignore warnings, that’s the main issue. Trust me, I saw this way too often.

If you cannot compile it than you have to fix it, otherwise just mark unused variables as ‘not an error’ via _ = someunusedvar.

Also Go: exceptions aren’t real, you declare and handle every error at every level or declare that you might return that error because go fuck yourself.
Because that’s sane and readable?
Wow. I’m honestly surprised I’m getting downvotes for a joke. Also, no. It isn’t. It really isn’t.

It is better than in most languages with exceptions, except from languages like Java, that require you to declare that certain method throws certain error.

It’s more tedious in Go, but at the end of the day it’s the same thing.

When I use someone else’s code I want to be sure if that thing can throw an error so I can decide what to do with it.

Java doesn’t have to declare every error at every level… It’s significantly more tedious and verbose than any other common language (for errors). I found it leads to less specific errors and errors handled at weird levels in the stack.
You know it’s social media when the one that’s right is downvoted
I’m with you, exceptions sound good but are a bug factory.
It’s better than “invisible” exceptions, but it’s still the worst “better” version. The best solution is some version of the good old Result monad. Rust has the BEST error handling (at least in the languages i know). You must handle Errors, BUT they are just values, AND there’s a easy, non-verbose way of passing on the error (the ? operator).
Beyond a quick “hello world” when it came out, I’ve never used rust, but that sounds pretty great
There’s nothing sane and readable about how Go insists you format dates and time. It is one of the dumbest language features I’ve ever seen.
Because that is sane and readable?
you can assign it to itself and it’ll be just fine. can’t put a breakpoint right on it, but it works
_, _, _ = unused1, unused2, unused3
Isn’t it the same with ES6?
I don’t believe so.

Are you sure?

That’s from ESLint, not javascript itself. JS doesn’t care about unused variables
I said ESLint
ESLint won’t prevent you from running your code, which is what the OP is on about. Hence the confusion in this thread.
Oh it will. At least in combination with Vue. At least that’s the default. Of cause yiou can disable it.
You’re describing many things that are not JavaScript the language. If you create and use tools that will stop you then yes they will stop you.
I said ESLint. Not Javascript. ESLint is a liter for JavaScript. That’s why I put JavaScript in brackets. Some people don’t know what ESLint is. I’m talking about ESLint the whole time. Its not JavaScript specific but it’s mostly used for JavaScript

There’s a load of confusion in this thread.

What the post is about is compiler based clean code enforcement. JS doesn’t do this, but your editor in combination with ESLint prevents you from running the program. However this isn’t a general JS thing, just the way your setup works.

Just saw your edit, and yeah, that makes sense as to the confusion.

Either way, your comment enquired as to whether it was “the same” and it still isn’t because for Go it’s a language feature and ESLint is not a language, it just allows you to create similar behaviour for JavaSvript which, by default, does not exhibit that behaviour.

JS simply does not care.
Depends on your eslint config, but yeah that’s an option.
You’re confusing it with your linter. Java script don’t care.
That’s why I said ESLint

I wonder what portion of all go code written is

if err != nil { return err }

It’s gotta be at least 20%

Can anybody explain the rationale behind this?
Exceptions don’t exists and ask errors must be handled at every level. It’s infuriating.
Hahaha, fuck no, I’ve dealt with exception-less code enough in my life, kthxbye
I think you missed a memo. Exceptions are bad and errors as values are in… I’ll have Harold forward it to you
I actually kind of like the error handling. Code should explain why something was a problem, not just where it was a problem. You get a huge string of “couldn’t foobar the baz: target baz was not greebleable: no greeble provider named fizzbuzz”, and while the strings are long as hell they are much better explanations for a problem than a stack trace is.
You’re meant to add annotations to the error to give it more context but we’re all lazy sometimes. I guess adding a construct to handle this more succinctly would encourage bad habits. Maybe something like ‘check(err, “More info”)’ could essentially be a macro for this but I’m not sure what the draw backs of that would be 🤷
a desperate fear of modular code that provides sound and safe abstractions over common patterns. that the language failed to learn from Java and was eventually forced to add generics anyway - a lesson from 2004 - says everything worth saying about the language.

The language was designed to be as simple as possible, as to not confuse the developers at Google. I know this sounds like something I made up in bad faith, but it’s really not.

The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt. – Rob Pike

"It must be familiar, roughly C-like. Programmers working at Google are early in their careers and are most familiar with procedural languages, particularly from the C family. The need to get programmers productive quickly in a new language means that the language cannot be too radical. – Rob Pike

The infamous if err != nil blocks are a consequence of building the language around tuples (as opposed to, say, sum types) and treating errors as values like in C. Rob Pike attempts to explain why it’s not a big deal here.

Errors are values - The Go Programming Language

Idioms and patterns for handling errors in Go.

People are scared of monads and think this is better.
My brain is too smooth to imagine a solution to this using monads. Mind sharing what you got with the class?
Having a Result monad that could represent either the data from a successful operation or an error. This can be generalised to the Either monad too.

Either[A, B] monad

Wait, that’s all monads are? some generic class Either?

Nope. Monads enable you to redefine how statements work.

Let’s say you have a program and use an Error data type which can either be Ok {Value: T} or Error:

int a = new Ok {Value = 1}; int b = foo(); return new Ok {Value = (a + b)};

Each statement has the following form:

var a = expr; rest

You first evaluate the “expr” part and bind/store the result in variable a, and evaluate the “rest” of the program.

You could represent the same thing using an anonymous function you evaluate right away:

(a => rest)(expr);

In a normal statement you just pass the result of “expr” to the function directly. The monad allows you to redefine that part.

You instead write:

bind((a => rest), expr)

Here “bind” redefines how the result of expr is passed to the anonymous function.

If you implement bind as:

B bind(Func f, A result_expr) { return f(result_expr); }

Then you get normal statements.

If you implement bind as:

Error<b> bind(Func > f, Error result_expr) { switch (result_expr) { case Ok { Value: var a}: return f(a); case Error: return Error; } }

You get statements with error handling.

So in an above example if the result of foo() is Error, the result of the statement is Error and the rest of the program is not evaluated. Otherwise, if the result of foo() is Ok {Value = 3}, you pass 3 to the rest of the program and you get a final result Ok {Value = 4}.

So the whole idea is that you hide the if Error part by redefining how the statements are interpreted.</b>

“Some generic class” with specific methods and laws, Monads are an algebraic structure and you want those laws included same as if you enable some type to use + you want to have a 0 somewhere and x + 0 == x to hold. Like “foo” + “” == “foo” in the case of strings, just as an example.

In Rust, Result and Option actually are monads. Let’s take Option as example:

  • pure x is Some(x)
  • a >>= b is a.and_then(b)

Then we have:

  • Left identity: Some(x).and_then(f)f(x)
  • Right identity: x.and_then(Some)x
  • Associativity: m.and_then(g).and_then(h)m.and_then(|x| g(x).and_then(h))

Why those laws? Because following them avoids surprises like x + 0 /= x.

Rust’s type system isn’t powerful enough to have a Monad trait (lack of HKTs) hence why you can’t write code that works with any type that implements that kind of interface. Result names >>= and_then, just like Option does so the code reads the same but you’ll have to choose between Option or Result in the type signature, the code can’t be properly generic over it.