5 ms·
TBH, if the backend were written in Go, this probably wouldn’t have happened to the extent it did. Somewhere in a log a descriptive error would have shown up.
by sneak 2y ago
TBH, if the backend were written in Go, this probably wouldn’t have happened to the extent it did. Somewhere in a log a descriptive error would have shown up.
One of the reasons I use Go whenever possible is that it removes a lot of the classic Python footguns. If you are going to rewrite your backend from
Javascript, why would you rewrite it in another untyped, error-prone language?
- TheDong 2y agoIn python it's harder to ignore errors than in Go. In go, I've definitely seen: tx, err := db.Tx() defer tx.Commit() // silently ignores the error on committing, which is the important one That would have masked this error so it didn't get logged by the application. In python, if you ignore an exception entirely, like I did that error above, you instead get an exception logged by default. Python's exceptions also include line numbers, where as Go errors by default wouldn't show you _which_ object has a conflict, even if you logged it. In general, python's logs are way better than Go's, and exceptions make it way harder to ignore errors entirely than Go's strategy.
- sneak 2y agoYeah, each have their benefits. I run all my go projects through golangci-lint which is required for merge to master/main, so not checking the error value would not have made it to prod. I suppose there are probably similar checkers for Python that would have caught the passing of a scalar value instead of a function. Perhaps this is an argument for mandatory linting in CI.
- randomdata 2y ago> I've definitely seen What did they say was the thinking behind it? defer tx.Rollback() would make sense, but defer tx.Commit() is nonsensical, regardless of whether or not the error is handled. It seems apparent that the problem there isn't forgetting to check an error, but that someone got their logic all mixed up, confusing rollback with commit.
- TheDong 2y ago"defer tx.Commit() is nonsensical" It's not pure nonsense, it works in the happy path, and it matches the pattern of how people often handle file IO in go. f, err := os.OpenFile(...) defer f.Close() ... which is another place most gophers ignore errors incorrectly. Just like the "defer tx.Commit()" example, it's collocating the idea of setup and cleanup together. Those two patterns are so similar, python handles them in the same way: with db.begin() as conn: # implicit transaction, gets automatically committed with open(...) as f: # implicit file open + close pair, automatically closed You're of course right that go requires more boiler-plate to do the right thing, but the wrong code has no compiler errors and works in the happy path, and fits how people think about the problem in other languages with sane RAII constructs, so of course people will write it.
- bryancoxwell 2y agoUnrelated but I’ve never really understood what to do with an error that gets returned by Close() aside from logging it. I’ve also never experienced that error being returned and don’t really understand what could even cause that.
- randomdata 2y agoA write is not guaranteed to be written if close fails. You almost certainly want to do something with the error state to ensure that the data gets safely stored in that case. If you are only reading, then sure, who cares?
- randomdata 2y ago> it's collocating the idea of setup and cleanup together. Okay, sure, but Rollback is the cleanup function. You always want to rollback – you only sometimes want to commit. I suppose this confirms that someone got their logic mixed up.
- owl57 2y ago> You always want to rollback This phrase highlights the confusion. If you learned SQL before Go, you want to rollback only on error. Every time I write `defer tx.Rollback()`, I cringe and have to remind myself that yes, it's actually ok to call a method called `Rollback` after succesfully writing data.