err != nil Is GOOD? (And Why)

  Рет қаралды 100,038

ThePrimeTime

ThePrimeTime

Күн бұрын

Пікірлер: 632
@DerekDoes...
@DerekDoes... Жыл бұрын
Love this a lot more than the typical 'reacting to videos' videos. Need like a playlist to be able to find these kinds of talks.
@reilandeubank
@reilandeubank Жыл бұрын
Yup!
@manacht2727
@manacht2727 3 ай бұрын
to be fair, prime can turn a 5 minute video in a 40 minute one lmao
@nisancoskun
@nisancoskun Жыл бұрын
In js, most libraries(native ones as well) throws errors that you may not know about. Sometimes this errors aren't even the native Error type. In Golang you know exacly what kind of error you are expecting, I like that explicitly.
@retishe7660
@retishe7660 Жыл бұрын
nice website 👌
@amotriuc
@amotriuc Жыл бұрын
libraries should specify what errors they should the throwing, if they don't it is a crappy library.
@mdbk2
@mdbk2 Жыл бұрын
@@amotriuc Or the language is crappy if everyone can just ingore errors.
@amotriuc
@amotriuc Жыл бұрын
@@swattertroops-yaaa what about them? See Java /C# Languages they do exception handling quite well. Including those ones. Bad ones are C++ JavaScript.
@amotriuc
@amotriuc Жыл бұрын
@@mdbk2 it is much easier to ignore a return code then an exception. If you miss an exception it will be caught on top level so you know it did happen. if you ignore result code no1 will know it did happen.
@JoshuaMaciel
@JoshuaMaciel Жыл бұрын
I absolutely love Go error handling. Honestly I hated error handling when I started learning programming because I started with JS. When I started Go, I hated the error handling until one day after writing a service in it and realized how nice it is, looks bad but who cares? It works well. I agree though that Rust does error handling better but Go’s is super simple along with everything else about the language
@NithinJune
@NithinJune Жыл бұрын
this!
@raenastra
@raenastra Жыл бұрын
agreed - in the big picture, syntax is pretty trivial; what it enables you to do matters more
@MomchilAtanasovHome
@MomchilAtanasovHome Жыл бұрын
Though rust error handling does a bod job about source of error unless you set the proper env variable in debug. With Go and wrapping, you get better pinpointing. From what I recall, Zig has the best error handling - the best from both worlds.
@Tony-dp1rl
@Tony-dp1rl Жыл бұрын
Disagree completely. Writing exception handling in Go is awful, because there is so much code that is NEVER executed, but is just there "in case" ... Just yuck.
@MomchilAtanasovHome
@MomchilAtanasovHome Жыл бұрын
@@Tony-dp1rl what do you mean by code that is never executed? If you know that it is never executed, just use underscore to ignore the error, otherwise it is a branch worth handling.
@noamprag9393
@noamprag9393 Жыл бұрын
Both Go and Rust use monadic error handling: Rust uses the Result monad while Go utilizes a monad known as "Writer" (which basically means a value with some other accumulated value, which in this case is the error). Rust is better in this sense because you cannot represent invalid states. On the other hand: in Go you could return `(nil, nil)` or both an error and a value. The result of this, is that error handling in Go feels more imperative and in Rust more declarative.
@Daniel_Zhu_a6f
@Daniel_Zhu_a6f Жыл бұрын
writer is when you append things to a list, hashmap, etc. (err, value) is just a pair, ie an anonymous product type. writers are useful outside of FP languages when you want to accumulate multiple errors or accumulate operations and execute in bulk or mock io.
11 ай бұрын
Agree, add to this that the Go compiler does not encourage (force) you as a programmer to handle the error case, it can be happily ignored. Whereas Rust compiler forces you to handle all cases making it impossible to access the return value (compile-time error) without checking for an error first. This is a huge win. The `Result` type and pattern matching in Rust are simply awesome.
@datguy4104
@datguy4104 Жыл бұрын
Then ironically when you use the return value from the JS function that could be a value or null, you'd still have to do an "if value === null" and handle that case too lol
@ekszentrik
@ekszentrik Жыл бұрын
What a stupid post upvoted by people who don’t use JS/TS. Null is never a native output in JS. It doesn’t happen on its own. Some programmer simply decided to use the “null” object. All empty references in JS are undefined. Don’t blame the language because your coworker or your own stupid face decide to return “null” objects either due to a cargo cult believe that value is useful, or because they need to signify an assigned but unused value.
@v0xl
@v0xl Жыл бұрын
by the way, null is the only case when == is preferable over === since it also handles undefined. (*only* undefined + null) aka x == null.
@Rknife
@Rknife 3 ай бұрын
but null !== null
@BrianGwaltney
@BrianGwaltney Жыл бұрын
Having coded full time in js/ts for 5+ years and 3 months in go, I'm 100% convinced go's way is better. Never want to go back having build production apps in both. In go, I know every error has at least been acknowledged if not handled correctly.
@natescode
@natescode Жыл бұрын
Go doesn't force you to handle it. Just write a bunch of ugly IF err != Nill checks. Proper wrapped error types are cleaner and guaranteed they're handled.
@BrianGwaltney
@BrianGwaltney Жыл бұрын
That's why I said at least acknowledge it. It's up to all of us to handle errors smartly. But at least I always know if a go function can error.@@natescode
@ocoolwow
@ocoolwow Жыл бұрын
OP should not be anywhere near a computer
@OnFireByte
@OnFireByte Жыл бұрын
@@natescode Every languages have the way to write ugly error handling. It's just that TS never tell you if it gonna throw or not. Go at least shows explicitly that error is possible without using any LSP, and if someone write ugly check it's just gonna be very obvious.
@aazzrwadrf
@aazzrwadrf Жыл бұрын
@@OnFireByte It's not explicit when the majority of nontrivial functions in your program are propagating an unknown union of errors up the stack. The issue with error handling in Go is you don't know what errors are being returned. It's nothing like Result in Rust.
@Grouloo
@Grouloo Жыл бұрын
Although returning a tuple is wayyyy better than throwing and catching, I still find it really awkward to handle. I think Rust and functional programming languages got it right by using a Result wrapper type / monad. That way you are sure that is one or the other and it cannot be the error and the value at the same time, moreover, you get methods and functions to deal with error handling in a really logical and secure way.
@themichaelw
@themichaelw Жыл бұрын
If you've ever worked professionally in Go _and_ in another language without error-by-value, I strongly think that most people would prefer EBV. It significantly reduces the cognitive overhead when you need to jump into an unfamiliar service/repo. No surprises on where errors might pop up from.
@reddragonflyxx657
@reddragonflyxx657 Жыл бұрын
I like Rust's Option and Result much more than Go's err. Usually (in code I write) if I'm handling an error I'm dealing with data from the code that may have encountered an error. A Result makes me decide how I want to deal with errors before I can get at the data (I can return the error with "?", panic on errors with ".unwrap()", convert to an Option with ".ok()", map Ok()/Err() values, do clever iterator stuff with arrays containing error values, and otherwise gain a lot of flexibility by having the error and data bundled together).
@tsanov86
@tsanov86 Жыл бұрын
Before Go I did a bit of Delphi and C. I hated try-catch in Delphi, I didn't know where to put, I didn't know where exactly it came from and if you did not set it right initially it was even worse to find what is happening in production. C was such a breath of fresh in regards of errors - very simple and understandable, but really annoying to deal all the time with memory allocations and leaks so when I found Go and had the chance I switched all the codebase to Go in the next few years. This was 5-6 years ago, I still think it was the right call. I have colleagues that when from Delphi to C# and to this day we have this debate where they consider try/catch superior
@orterves
@orterves Жыл бұрын
I am primarily a C# developer. Exception < (value, Err) < Result, simple as that. The problem with exceptions is as soon as they are possible in a language, they can happen anywhere and everywhere, for any reason, without warning. They are awful for having certainty about how the program will behave. Results are superior especially when the language has the ? or equivalent operator to pass the handling up the chain and otherwise enforces the handling of both cases, but I frequently try catch Exceptions in C# as early as possible to convert into a Result type just to get a little control back
@johnblomberg389
@johnblomberg389 4 ай бұрын
If there is something I really love it's jumping into a new codebase and the previous developer decided to make a "resilient" and "error handling" application that just does err != nil checks everywhere but instead of actually handling it in a meaningful way just returns it up the stack. Now I suddenly get a error code somewhere but I have no idea where the error originally happened or what could have caused it because the stack is unwound and the program already exited... I really love to then start hunting down all places where the return err is used and add logging just to be able to try and catch it 😍
@duckner
@duckner Ай бұрын
​@@orterves I never liked Result, (value, error) feels less boilerplaty and more control. Result is just an abstraction of it
@einargs
@einargs Жыл бұрын
I like errors being part of the return type. My problem is that instead of using typed unions / associated value enums / algebraic data types, which is the correct, type safe way to deal with this, where accessing the value requires you to branch on having an error or not... they made it a tuple of nullable values. I guess it's good for a simple language that doesn't want extremely basic and important features for modeling data like being able to represent mutually exclusive states. (I'm salty.) That said, e.g. LLVM does errors like Go (with a custom wrapper return type) and it's really fun. On the other hand, I also really like Elixir style error handling. Elixir is built to do incredibly fault tolerant distributed systems where lots of things can error. So the idea is don't handle individual errors; any time there's an error, just recover from a known good state.
@JohnNowak-p1g
@JohnNowak-p1g Жыл бұрын
What if 95% of errors in your app just need to be logged and corresponding http status code returned? It's more more convenient to let those errors bubble up to a centralized error handler instead of repeating err != nil checks all across the call stack. The other 5% are usually retries/circuit brakers etc. which are handled by libs (talking about web services in this case)
@patrickramos1748
@patrickramos1748 Жыл бұрын
this is the one for me, in most of the code i write, 95% of the time an error happens i just want to rollback the transaction, do some logging, and respond with 500, all of which go in a middleware. that way, i dont have to think about exceptions most of the time
@ANONAAAAAAAAA
@ANONAAAAAAAAA Жыл бұрын
100% agree. I also would recommenced to use error monitoring services like Sentry along with logging, they make life a lot easier.
@mmmk189
@mmmk189 Жыл бұрын
If you want to handle errors by value in javascript you can adopt that convention and return a tuple like in go. Then the code will look very similar to go. The code in this video is complex because you are translating error via exceptions into error via return value. If you use exceptions all the way through then in javascript you will just do .catch on your calls to foo and bar and do your handling in there which is imo a lot cleaner than go
@z0n_
@z0n_ Жыл бұрын
I think it really depends what type of software you are building. For example: If you are building a basic CRUD Web API , I would guess +95% of the errors are "unrecoverable". Like if your database connection fails, what are you going to do? If you have bug in your business logic? If you failed to validate the request parameters correctly? For all of these cases there is no "recovering" from them. So having such fine grained error handling makes no sense. You can handle all of these with middleware (single try/catch). It's bit different when you are building something where not-recovering isn't really an option, like an operating system, IOT related or something where there are no transactions to save you. It boils down to using the right tool for the right job.
@ANONAAAAAAAAA
@ANONAAAAAAAAA Жыл бұрын
Totally agree. Errors in backend are unrecoverable for the most cases. The only things can be done are: report or log errors, rollback DB transactions and show users sorry messages. It's better to return meaningful messages for user-input-validation errors though.
@isodoubIet
@isodoubIet Жыл бұрын
I think this is pretty much true across the board, regardless of domain. I mean realistically, what strategies are even available to recover from most errors? Trying again?
@z0n_
@z0n_ Жыл бұрын
@@isodoubIet Yeah, I guess "recovery" is not the correct word here. It's more like generic and non-generic error handling. Most errors can be handled in a generic way but I can imagine situations where application/tool has a lot of internal state and you have to essentially rollback the mutations manually when errors happen. I can see try/catch being really clumsy in those situations.
@isodoubIet
@isodoubIet Жыл бұрын
@@z0n_ I suspect this is not possible to in TS/JS so this might explain why so many in this audience have issues with exceptions, but in C++ you can design things so that everything rolls back automatically in the case of an exception. When an exception is thrown, stacks will unwind and destructors will run. You then have several options for how to deal with rollbacks. You can divide your work in a prepare/commit fashion (so that all possible exceptions are thrown in the "prepare" stage, and all changes in system state happen in the commit stage), or you can have custom types that explicitly roll back changes when destroyed, unless explicitly dismissed. A third option, which may sometimes be possible, is to not rollback completely but to allow things to be in a valid but unspecified state after an exception is thrown. Either way you're never rolling things back manually, which is pretty clunky no matter what error handling strategy is being used but surely unworkable in the presence of exceptions.
@jeffreybritton3338
@jeffreybritton3338 Жыл бұрын
@@z0n_Or either use a transaction system or defer state modification to the final step of an operation where it can’t fail.
@DmitrijKudriavcev
@DmitrijKudriavcev Жыл бұрын
As old-school C programmer, I can tell that this sort of error hanling was in the C forewer. You always return an error code and then you have an if statement to handle this error code. The Go haven't invented anything new here, except now you can separate an actual function response from the error that gives you this nice shugar. The main problem with this error handling is precisely a mess of if or switch statements after each function. You need to handle every error and then pass it on to the caller by wrapping it into another error what happens (face it) in 80-90% of the cases. But this extra code can be source of all sort of bugs because it is unnecessary operations that language forces you to do after every function call. Not only that, but you cannot chain call the functions this way. Lets say you have a function that return a string and another one that parses this string and returns integer. Because you must handle errors, you will need to process the first function response then call the second one and process its response as well. While you don't care if the first function didn't return a string or if the string wasn't a valid integer and the second function have failed, you will have to handle error twice and return a nil, err in both cases. This is why exeptions in C++ and Java was so great, it eliminates the need of doing that. You can handle errors in one place, you don't need an if statement after every function. There is no real problem to find out what function have failed, all you need is to know what type of error have happened and you can achive it by throwing different clases of exceptions. And thanks to inheritance you can group similar exceptions into groups by subclassing them from the some base class and handle this base class. It gives you way more flexibility on how to handle errors in your application and where to handle them. I will not be surprised if exceptions will be introduced in go at some point.
@vladislavkovechenkov8473
@vladislavkovechenkov8473 Жыл бұрын
Thanks a lot for the vid. I'm only starting with Go and I was quite confused that error handling in Go was criticized this much, as to me it looked fine after years with JS. Yes, annoying, but as someone said on the internet "at least it makes you pretend you thought about how to handle potential errors", which sounds like a win for me. Maybe I haven't yet written enough Go and I'll have a better idea of where this pattern falls short as I run into more cases of handling errors, but for now I'll move forward with confidence writing Go and not stress about that error handling is "ugly". Also, thanks to everyone who added perspective in the comments sections, I learned a lot while reading about nuances of this pattern!
@theowenmccarthy
@theowenmccarthy Жыл бұрын
To be fair, as someone who regularly grumbles about Go's error handling I'm not advocating for it to be more like JavaScript's with Try catches, I just want like a '?' operator that would be the equivalent of "if err != nil {panic(err)}" and another like "?{return err, ...}" that would be the equivalent of "if err != nil {return err}" or "if err != nil{return err, nil, etc.}". When I need to do some custom error handling, Go is the best, but when I'm just testing something out or I don't expect any errors that shouldn't be returned I'd rather not have to constantly copy and paste the same codeblock.
@DemonButt3r
@DemonButt3r Жыл бұрын
This is all I want as well. I dream about it
@nskeip
@nskeip Жыл бұрын
Not sure if '?' operator should panic
@ja31ya
@ja31ya Жыл бұрын
If you're just testing stuff out, why not use the placeholder character "_" ? Then you don't have to handle the err case.
@MomchilAtanasovHome
@MomchilAtanasovHome Жыл бұрын
? should not panic, it should propagate. The problem with pure propagation is that you have leaky abstraction. If you treat each package as standalone OS library, it should propagate typed errors from its package, hence just using ? is not applicable in that package's implementation. Rust fails at that as well. I would like tike have `.ErrOnFail(err, "%w: error creating database user: %w", ErrInvalidState, err)` which would propagate a wrapped error.
@oxidant5
@oxidant5 Жыл бұрын
@@ja31ya exactly
@IvanRandomDude
@IvanRandomDude Жыл бұрын
Exactly. It is comparing apples to oranges. Equivalent Go code to "const val = await foo()" would be "val, _ := foo()". See, it is even shorter and easier to read :)
@zaneearldufour
@zaneearldufour Жыл бұрын
Aren't panics way worse to deal with than JavaScript errors?
@ThienNguyen-bg1kx
@ThienNguyen-bg1kx Жыл бұрын
@@zaneearldufour not if we talking about a panic in http handler with proper recovery middlewares
@Gusto20000
@Gusto20000 Жыл бұрын
@@zaneearldufourhow exactly you get panic from val,_ := foo()? Or you think it won’t panic if you write val, err := foo()?
@arturfil
@arturfil Жыл бұрын
@@zaneearldufour You don't use panics for error handling typically, you use panics for situations where you can't keep on running your program and thus you panic and see the stack trace of where it panics. I.E when you don't set the port properly for a server (use letters for example) and you have to stop the server so that you correct that before you keep on going with running the program.
@comradepeter87
@comradepeter87 Жыл бұрын
@@Gusto20000 I have not written Go (I do write Rust btw), so I don't know what's the value of `val` when err == nil. But isn't the only logical choice being that it must be nil? In that case, using val should result in some sort of panic shouldn't it?
@amirhosseinsoleimani5410
@amirhosseinsoleimani5410 Жыл бұрын
Absolutely right! The messed up part is, lot of Devs prefer smart looking or cleaner code over secure or more stable code! Btw I love go's error handling or generally, "Errors as value" over old school "Exceptions"
@dealloc
@dealloc Жыл бұрын
Old school would be to pass the error through arguments, or return an int with negative values, and is arguably worse; If you need the error message you then have to call `strerror(errno)`. Couldn't be anymore magic in my eyes. The problem is not exceptions but the language's ability to provide proper ways to deal with them and convey information about them. A language should provide ways to mark functions and things like pattern matching, operators, guards, etc. to handle them. Not just try/catch, which is arguably the worst way to deal with exceptions.
@LusidDreaming
@LusidDreaming Жыл бұрын
@@dealloc try catch is what makes exceptions what they are. Maybe there is a different syntactic way to express this, but exceptions (in the context of things you "throw") will always have the undesirable behavior of being inherently different than other normal values. Its the ability to throw something up the callstack implicitly that (in my opinion) causes issues, not just the scoping issues with try catch blocks. Being able to throw an exception is essentially a goto statement without an explicit label. They can make the control flow of an application hard to understand and they inherently break locality of behavior. They are also harder for static analysis tools to reason about. I will say that Java forcing explicit definitions of what exceptions may be thrown from a method at least gives more explicit information and helps with static analysis. But it still suffers from the non-locality of behavior issue. Having errors as values means you don't need separate constructs to handle errors. They can be handled like any other value in your system, which leaves a lot more flexibility in how you handle your errors. Even when exceptions are values (like being objects in Java), you still have to use special syntax to extract them and pass them around, and I've rarely seen that ever done. You essentially create two separate control flows for your system, one of which is implicit.
@eNtrozx
@eNtrozx Жыл бұрын
Yeah but the annoying things is that if you want the error to bubble up, you still have to handle it
@ficolas2
@ficolas2 Жыл бұрын
Which is one of the reasons why rust does a much better job, you can just use the question mark
@SandraWantsCoke
@SandraWantsCoke Жыл бұрын
yes, but you simply return the error
@eNtrozx
@eNtrozx Жыл бұрын
@@SandraWantsCoke That's handling, you write actual code that does that
@PamellaCardoso-pp5tr
@PamellaCardoso-pp5tr 11 ай бұрын
At this point people just need to start implementing their own Maybe/Either/Result Monad, its not that hard at all, its actually insanely simple, Just a couple 5-6 functions and you're good to go. Monads can be implemented in any language and they're insanely usefull (Just look at rust)
@eugeneponomarov7429
@eugeneponomarov7429 Ай бұрын
When you need errors to bubble up - you have to question your architecture.
@flammea_
@flammea_ Жыл бұрын
No Joke. Why would I handle a potential error from JSON.parse? What am I supposed to do with the JSON.parse error?
@alberto3641
@alberto3641 10 ай бұрын
no one really knows lol
@LinxOnlineGames
@LinxOnlineGames Жыл бұрын
I think this moves onto another interesting point, exceptions are meant to be exceptional (or so the saying goes), while Go's error is par for the course. Many developers use exceptions as an 'all hope is lost' - because if it wasn't that type of situation then it wouldn't be exceptional (stacktraces are expensive afterall). I've seen many a function written that instead of throwing an exception, would return false, or an error object, as the problem that arose is expected and part of the potential flow. From this video, I get the impression that an error is an error, no matter where it comes from in Go's paradigm.
@mctechcraft7
@mctechcraft7 Жыл бұрын
One thing I did in my C# code was add an extension method to Task that just is a wrapper around a try catch that returns a (T, Exception?) tuple that lets me do this and wrap existing methods so that I never get exceptions
@jefersonnl
@jefersonnl 3 ай бұрын
When I was introduced to Java and had like 6 months to start writing production grade code, almost 20 years ago, I was annoyed one had to try-catch all the time, but ohhhh boy!! Did that prepared me for future experiences with post-Modern hype driven development languages... It got drilled in to me that anything can fail at any time.
@ilushkinz4424
@ilushkinz4424 Жыл бұрын
The main point of try-catch approach, is that, in 99.9% of all webapps, or even on 70-80% of software, you do not care about which error is occured. If you look at the go code, which has, for example, stack trace of 6 inner function calls, in each of these function calls you probably just sending the error upwards. And this exactly why it sucks. Mostly, you just propogate the error up to the main function, and in this case, you try-catch just does it better, it does it automatically without you requiring to do redurant error checks. Another thing what is bothering me about go error handling - it is not restrictive, you can just ignore the error, and it will panic because of that
@marcs9451
@marcs9451 Жыл бұрын
ignoring error states is possible in any language, being able to explicitly not care about the error state is totally fine in some cases.
@marcs9451
@marcs9451 Жыл бұрын
And no. Try-Catch does not work lile you said, the error is not merely propagated, the stack itself is *unwinded*, it's very, very different at a fundamental machine level. Simply propagating the error value as a return is jist another data transformation in your call graph and you can handle it with regular control flow.
@gagagero
@gagagero Жыл бұрын
​@@marcs9451The stack is not necessarily unwound. It is in most languages but that's because the language designers were lazy.
@taatuu25
@taatuu25 Жыл бұрын
@@marcs9451 What's the difference? isn't "unwinding the stack" the same as propagating up the stack?
@isodoubIet
@isodoubIet Жыл бұрын
@@gagagero Lol what would have been the "non-lazy" choice?
@MatthewAhrensTech
@MatthewAhrensTech Жыл бұрын
Either your effects are in your types (tuples, monads, a failure ADT) or they are in their own effect system (exceptions, signals) I'm glad you mentioned a monadic approach. It comes down to the same tradeoff: I want control -> handle it all in line I want ease of expression -> abstract error handling from the "happy path" computation Different tools for different jobs
@Luxalpa
@Luxalpa Жыл бұрын
Or use Rust and just get both?
@itzhakeretzkdosha6875
@itzhakeretzkdosha6875 Жыл бұрын
Will golang ever go the 'Result' path? I'm missing that and union types in GO
@OnFireByte
@OnFireByte Жыл бұрын
union types might be possible. But for result type, it's certainly not. Imagine everyone have to update their codebase to change from (T, error) to Result[T]
@climatechangedoesntbargain9140
@climatechangedoesntbargain9140 Жыл бұрын
​@@OnFireBytenot everyone has to do that - they're compatible
@tonyb3123
@tonyb3123 Жыл бұрын
I pretty much never have to read actual stack traces in Go, because I'm hyper dilligent about wrapping _every error_ returned in `fmt.Errorf("some context: %w", err)`. It's genuinely jarring to go back to a Node environment and have to dig through a jumbled stack trace after writing Go and every error is telling me exactly what went wrong in plain english. I like to tell people, if you have to dig through an error's stack trace to know what went wrong and where, your error handling is wrong.
@thehibbi
@thehibbi Жыл бұрын
In principle I like that idea, but what would happen if many concurrent tasks print to stderr at the same time? Does Go have some nice way to handle that? It's a genuine question for a real problem. Rust has the tracing crate for that.
@superderpyderps
@superderpyderps Жыл бұрын
​@@thehibbi fmt.Errorf isn't a print statement, despite looking like one. It's actually wrapping the error and is then typically returned to the caller. So the answer is, wherever you're actually logging errors will have the full stack for its specific error, meaning if you have a batch of errors, you'll see a "stack" for each error you logged individually. Also, stdlib added some other nice conveniences around the same time, allowing you to aggregate multiple errors into a single error and then be able to unwrap them alongside their individual traces. So you could choose to only log at the top most level even if somewhere in the chain you were aggregating multiple errors
@thehibbi
@thehibbi Жыл бұрын
@@superderpyderps ah that's good to know. Thanks for the explanation!
@Sw3d15h_F1s4
@Sw3d15h_F1s4 Жыл бұрын
i think it was Java that has "throws [some type]" for method signatures? so you know exactly what error is thrown and by what? seems like a decent solution, yeah its a bit boilerplate but at least theres a heads up.
@phoenix-tt
@phoenix-tt Жыл бұрын
It could have been a lint at least. Typescript's had this proposal for a long time, yet it hasn't been merged.
@Slashx92
@Slashx92 Жыл бұрын
The multiple try/catch with outside variables is exactly how I'm dealing with errors in critical processes of an erp we automate lmao. Shit's so ugly
@little-ghost-rider
@little-ghost-rider 7 ай бұрын
You can just create some wrap function So that it returns undefined rather than throw error
@dranon0o
@dranon0o Жыл бұрын
``` var err error if err = something(); err != nil { return errors.Join(fmt.Errof("specifics %v", value), err) } var data Blabla if data, err = other(); err != nil { return errors.Join(fmt.Errorf("some specifics %v", value), err) } ``` You did talked about this sir That's how you create wonderful errors management in `go`
@mintx1720
@mintx1720 Жыл бұрын
The problem is actually because of the error, you can't use the result immediately in the same line, ever. Even simple things like string to int, getting a value from a map, etc.
@rt1517
@rt1517 10 ай бұрын
Depending on the context, implicit error management can help you write simpler code, while explicit error management can help you write more robust applications. I would argue that it is almost the same with garbage collector and RAII. With garbage collector and/or RAII, you can write simpler code. But you are pushed/forced to ignore errors in destructors so your application is not as rigorous as it would be with explicit resource management.
@programaths
@programaths Жыл бұрын
You can also mitigate the issue. I do Apex, and I have objects with embedded error handling. That sounds weird since it breaks the single responsibility principle, but it simplifies the code for the caller. You can chain methods using the same objects; each method knows to bail out if you provide an error. This means you can write your implementation and check for errors in one place, handle the error anywhere, and provide an error-free object to continue the chain. The API is mostly for noncoders who can't handle errors (they don't even think about it), so it has to be as robust as possible. And by avoiding throwing exceptions, it's made very explicit. The language doesn't support Generics; otherwise, I would have done a wrapper with overloaded methods accepting those wrappers.
@greendsnow
@greendsnow Жыл бұрын
I wish there were a single liner error handling with Go, though.
@samfelton5009
@samfelton5009 Жыл бұрын
What language has single line error handling and what does it look like?
@antongorov5275
@antongorov5275 Жыл бұрын
Kinda like "expect" in Rust?
@paulooliveiracastro
@paulooliveiracastro Жыл бұрын
Zig's try/catch are very cool, but the language has to treat errors as something special. In Go errors are simply some value that you return.
@andreffrosa
@andreffrosa Жыл бұрын
​@@samfelton5009 C has more or less when you use the return value for errors. if(err = f(n)) {...} When err is a non-zero int, the if evaluates to true and you deal with the error. The "downside" is that you have to use pointers as out-parameters for setting normal results
@notuxnobux
@notuxnobux Жыл бұрын
@@samfelton5009 zig. In zig instead of "if err != nil return err" you have "try". The try in zig is not exception handling, it just does the go err != nil part automatically. For example: try func(); instead of: value, err := func() if err != nil { return err } that zig version is the exact same thing as the go version
@PeterBernardin
@PeterBernardin 8 ай бұрын
There's a package called neverthrow that's quite cool, even though it's a bit awkward, it adds that extra layer of security to JS/TS. Takes the mysteries out of errors, and forces you to handle them. To me personally though, although I like the philosophy behind Go's error handling, my issue is that there's no shorthand for the err = ... / err != nil stuff. That pattern is just so common that I just feel it can be shorthanded to like an "or". Something along the lines of `someVal := someFunc() or { handle error }` and the compiler just forces you to handle the error.
@Tobsson
@Tobsson Жыл бұрын
If err := doSomething(); err != nil { Handle error } Is something I find beautiful. Wish it would work even if a value is returned.
@dimitro.cardellini
@dimitro.cardellini Ай бұрын
1:29 In go you don't know which error has been returned as well. You know where from it was returned, but definitely not which one exactly. It could be fixed in Go by specifying concrete type of error, but the general rule is to specify just an`error` - the widest as possible. So, Go just forces a developer to propagate manually, like nodejs did with err-first callbacks.
@ishi_nomi
@ishi_nomi Жыл бұрын
This totally make sense but is a bit weird though. I mean, the go-style error handling here is just what all language without try-catch simply do. C also do that, just without the tuple-like return syntax.
@youtubeenjoyer1743
@youtubeenjoyer1743 9 ай бұрын
The mistake of the Go design is that Error is a separate thing that needs its own interface. Instead of treating "error" conditions as Errors, you can just treat them as normal conditions.
@crum--business
@crum--business Жыл бұрын
You can add .catch after the method function foo() { method1().catch(err=>/*handle it*/) method2().catch(err=>/*handle it*/) method3().catch(err=>/*handle it*/) method4().catch(err=>/*handle it*/) } More like this function foo() { const value1 = method1().then(res=>res.json()).catch(err=>/*handle it*/) const value2 = method2().then(res=>res.json()).catch(err=>/*handle it*/) const value3 = method3().then(res=>res.json()).catch(err=>/*handle it*/) const value4 = method4().then(res=>res.json()).catch(err=>/*handle it*/) }
@emilemil1
@emilemil1 Жыл бұрын
This obviously differs, but at my workplace we do very minimal error checking because even when functions can error, they shouldn't, because we control the input. The only places where we really check for errors is for network requests where failure is out of our control. If something breaks and we get an unexpected error then the appropriate response (for us) is to let that error bubble to the surface so we can fix it, not attempt to handle it which often results in suppressing bugs.
@chudchadanstud
@chudchadanstud Жыл бұрын
No such thing. You're pretty much relying on humans not making a mistake. The issue with the "bubble to the top" nonsense is that errors can get masked and transformed along the way. You also don't know how much damage it has done along the way. Handling errors is about soft landings when mistakes occur, or creating self healing systems. Remember, failing to prepare is preparing to fail.
@gileee
@gileee Жыл бұрын
​@@chudchadanstud No, if someone makes a mistake in their input, that's still their input they're responsible for. Errors don't get "transformed along the way" and any error causes the system to stop processing the entire request so nothing is changed if an error occurs.
@isodoubIet
@isodoubIet Жыл бұрын
@@chudchadanstud " The issue with the "bubble to the top" nonsense is that errors can get masked and transformed along the way. " That seems to suggest a fundamental problem with how your overall system design approaches errors. There shouldn't be any opportunity for errors to be "transformed along the way" because you should only have error handlers at or near the top level in the first place. If you're trying to "handle" errors by wrapping a try catch around every function that can fail, you're working against how the scheme is intended to be used and setting yourself up for these kinds of problems. Disclaimer: I don't do JS/TS and my experience with exceptions comes from C++ where they actually make sense.
@chudchadanstud
@chudchadanstud Жыл бұрын
@@isodoubIet Bubbling to the top doesn't guarantee that your error won't be transformed. You're just throwing an exception and hoping someone else handles it, hoping that the system crashes or the process/request is killed unpredictability. You're also killing a process for a useless error. The Go styles ensures that your not placing your errors on hopes and dreams and that your function only throws errors in needs to throw. Consider that you press a stop button in a machine and during the clean-up operation a files fails to close. That is a trivial issue, your machine shouldn't crash or cut the power because a file failed to close. You can simply log the error and move on with the rest of the steps.
@chudchadanstud
@chudchadanstud Жыл бұрын
@@gileee What of you have multiple erros that occur whilst your bubbling to the top. How do you catch those?
@chickenduckhappy
@chickenduckhappy Жыл бұрын
Catching exceptions all the time is nonsense. They're best used for unexpected errors. Return values, callbacks, wherever are much better for expected errors that need to be dealt with as part of normal control flow.
@gileee
@gileee Жыл бұрын
True. No one actually writes js code like he did in this example.
@Slashx92
@Slashx92 Жыл бұрын
​@@gileeeHi, we automate an erp with javascript (it's scripting languaje) his example is exactly how we deal with errors to do the proper rollbacks. When you care WHAT failed, you have to do that try catch hell
@davidmcdonnel4831
@davidmcdonnel4831 Жыл бұрын
@@Slashx92This, as long as you are writing an application that does something you are going to want some sort of fault tolerance. What if the network goes down? What if the filesystem isn't available? What if there isn't enough ram to complete the operation? How do you fail gracefully? What happens to the logs? How do you recover? Do the users need to be prompted that their action failed?
@ACuteAura
@ACuteAura Жыл бұрын
go's error handling has worse warts, like it being entirely untyped strings with no proper interface, we had this huge file full of string matching "things the net and net/http can throw" to status code and error message conversion in our reverse proxy, implementing basically all cloudflare error codes and some extra because we had this stupid SAP app as a customer that only logged status code and they had connection issues.
@marcs9451
@marcs9451 Жыл бұрын
Yes, I much prefer error enums like Zig/Odin/Rust. Go's biggest weakness is not having real enums and unions
@heavymetalmixer91
@heavymetalmixer91 24 күн бұрын
Gotta agree, I preffer when the language forces the errro handling to be explicit. It's easier to understand what's going on when reading the code.
@beofonemind
@beofonemind Жыл бұрын
thanks for hammering this home. I've been telling myself not to cut corners with error handling. I will reap the benefits of it later.
@rzabcio3
@rzabcio3 Жыл бұрын
I hated Go's err handling. Until I launched my first maybe small but serious app and there were no errors, fatals, boundary cases or anything like that. I just couldn't believe it! After 15+ years in IT, one's used to getting unexpected errors, NPEs and similar snafus all the time, especially during first tries. But in Go... NOTHING. At first I thought I screwed up so badly, I missed some errors. But there is the point - it is impossible to miss errors in Go, I correctly managed all situations! It was love from the second sight. ❤
@TacticalEntropy
@TacticalEntropy 4 ай бұрын
He touched on it right at the end. The really problem is not that it returns the error. Returning errors rather than throwing them makes them explicit and 100% better. The real issue with go is that "if" statements everywhere is such a shit way to then handle those exceptions. Error handling should be built into the language as a first class citizen and languages like Scala that allow you to then pattern match and using things like map, flatMap, for comprehensions, etc are such a better way to handle things. Sometimes you don't need to care about every place it could fail. Sometimes you want to just write code that says do these things as long as they keep working and let me handle the failures at the points I care about. While is why using a Monad and gaining fluid support for chaining map operations is great.
@madskaddie
@madskaddie Жыл бұрын
this one I'm not with prime. Note that I also prefer return value based errors, but if the model is exceptions, than for the most cases, the error is forwarded to the client (we can discuss if the forward model is correct - vs wrapping the error, but that is other discussion. And in the go example, the err is also forwarded) assuming error forwarding is the model, exceptions minimize undefined behavior by nature. period. no one with experience would return null on the catch branch. It is simply wrong. that is for the client to choose, not the implementation I prefer return value based because i really like funcional pipelining and function composition. having a try/catch is a mess to compose (the exception behavior is like a non linear, hidden, return value). I like linear control flow. But having that control does make the happy path less clean. choices
@PerfectMakanju
@PerfectMakanju Жыл бұрын
This days I tend to use a library like purify-ts to wrap my Promise codes in Javascript. I find it insane not to be able to reliably know what errors a function throws or even be forced to handle it. This however means that I'll have to be using creating more functions to handle errors (like .then promises handles)
@romsthe
@romsthe Жыл бұрын
Error handling is hard. We have automated coredump analysis and monitoring to make sure it cores in the usual places we don't bother to fix 😅
@CodyDBentley
@CodyDBentley Жыл бұрын
Something we do at my job is if/else chaining related blocks, and I haven't really seen it done in other places. All the values are scoped to the entire if/else chain, and the only downside is sometimes function signatures can break the blocks if it has no error branch, but most things we write or interact with have error returns. Example (assuming foo and bar are int values or something): ``` if fooVal, err := foo(); err != nil { return 0, fmt.Errorf("foo failed: %w", err) } else if barVal, err := bar(); err != nil { return 0, fmt.Errorf("bar failed: %w", err) } else { return fooVal + barVal, nil } ```
@dzisonline
@dzisonline Жыл бұрын
My biggest issues with errors are not mine but library's. Hunting errors in huge libraries is quite tedious.
@danielmelo389
@danielmelo389 Жыл бұрын
VBA error handling, you can add a number in front of every line of code, so when an error happen you can point out precisely where it happened and why. Is it perfect? no. Is it any good? Also no. Have to add line numbers is a real mess
@ckpioo
@ckpioo 4 ай бұрын
why is no one talking about how he just ignored .catch?
@heronshorts
@heronshorts 3 ай бұрын
yeah you can use .then and still return your value with only one .catch
@jasonscherer2631
@jasonscherer2631 Жыл бұрын
I learned how much this makes sense after now doing a golang code base, I love it so much more.
@aaaaanh
@aaaaanh Жыл бұрын
hmm, Go error handling used to make me suicidal cuz it's a pattern I'm not used to. After 2 weeks of usage, I went back to typescript to build out something else and realized Go handling is way better. Then I learned Rust and everything else was history.
@qwelias
@qwelias Жыл бұрын
That works only if you treat errors as uniq special cases and thus need to handle them with uniq special code. How about just don't? In your average HTTP API server if you fail to parse JSON just let the error bubble up and return some sane description to the user. Same goes for most of business-logic cases, if the error is thrown manually it should be descriptive and it should be handled by top-level handler that will just send it to the client in a nice way; but if it's not a manually thrown one then it's probably a server fuckup (i.e. 500), if it's on a cricial path -- sure handle it with some cleanup, but that's rare. Most of your APIs should be stateless too, unless you're from 2000s.
@dealloc
@dealloc Жыл бұрын
The real problem with JavaScript is that they don't have the necessary language features to provide a good way to handle errors. They should honestly look at Swift's approach, which is very similar albeit much more powerful thanks to pattern matching, guards, and other language features that makes it a breeze to work with. Exception-based error handling is bad when the language doesn't provide ways other than try/catch to deal with error propagation. I'd say the same for Go. They should provide ways to invert the error handling, or make it implicit, like Rust does with the ? (previously try!) for Optionals and Result (as long as the return type is also Result/Option)
@dealloc
@dealloc Жыл бұрын
Also Prime's example of using try/catch is not equivalent to handling the error with != nil in Go. In Go the error propagation is explicit (return err), whereas in JavaScript and other languages that use exception-style error handling, they are implicit or "automatic". You can still handle the error in a function and then rethrow the error to propagate the error. It's just a separate control flow, which Go doesn't have, so it's not 1:1. The major drawback of JavaScript is that there's no way to mark a function as throwing. It's a lack of syntax problem, not a conceptual problem.
@nehua6164
@nehua6164 Жыл бұрын
Can't you use the promise syntax to chain a then() to return the value and a catch() function to handle the error in JS? Seems like a skill issue.
@esser50k
@esser50k Жыл бұрын
learn to love go error handling. It actually makes the code super easy to read, for the happy case you just read whatever is on the left side of the code (the editor often even just hides the return err lines). It also makes it super easy to test your functions and make them go into every error case..
@bloody_albatross
@bloody_albatross Жыл бұрын
Yeah, I prefer Rust's error handling over Go's.
@JeffCaldwell-nemo_omen
@JeffCaldwell-nemo_omen Жыл бұрын
Man, I'm just picking up Go as someone who's primarily coded in JS/TS and watching this makes me feel more sane. Up to this point I was just like "Wow, handling errors is such a gigantic pain in the ass." Go may not have ideal error handling, but it's so much less complicated than handling try/catch forks, especially in the lower layers of an app.
@mementomori8856
@mementomori8856 Жыл бұрын
I LOVE it personally, just deal with your error right away and be done!
@Fernando-du5uj
@Fernando-du5uj Жыл бұрын
Thank God, I was waiting for that last "...agen". I thought you will not do it.
@apollolux
@apollolux Жыл бұрын
I will fully admit that when I initially write JS for myself that I don't immediately write error-checking into my code. That being said, if I expect that code I'm writing is either going to be used by other people, some level of "robust" beyond "this is a thought experiment or some hacked up localhost toy project," or both, then you bet I do whatever I could to error-check (and hopefully error-proof) the living daylights out of it, including making sure that if I _intentionally_ add any throw statements in my code under the assumption that my code can be dropped into third-party projects that what I throw is reasonably meaningful and understandable (at the bare minimum a contextually proper error message). Granted, it would be easier if we didn't have to memorize or otherwise check MDN for what throws and what doesn't every time we wanted to localize our own error-checking, but I'm no stranger to having a language reference open in another tab or multiple tabs in another window. Which reminds me - I need to reinstall onto my dev computer the userscript I made in 2019 that puts links to MDN's JS reference as a toggleable sidebar.
@philipp04
@philipp04 Жыл бұрын
I've got C++ at university programming classes (I'm studying maths but we do have some programming) and my professor just outright banned exceptions for low performance, weird ass implementation and being wack in general lol. The man is also a CTO of a company which develops software for finding petroleum sources in the ground, the project takes fuckin 20 minutes to build and it has no try catch anywhere in it
@romsthe
@romsthe Жыл бұрын
And he's right. Status checking like in go is better for perf and maintenance. He will probably tell you to use std::expected now that it's there
@isodoubIet
@isodoubIet Жыл бұрын
"my professor just outright banned exceptions for low performance, weird ass implementation and being wack in general lol." He's wrong on all three counts. Exceptions perform better on the happy path, the implementation is just fine, and they're very easy to understand.
@Tuniwutzi
@Tuniwutzi Жыл бұрын
@@isodoubIet Super agree. Especially in C++, where you can avoid writing try/catch in 99% of cases by just using RAII, exceptions are by far the best way. A bit sad that professors are teaching this nonsense when the C++ standard itself encourages the use of exceptions.
@isodoubIet
@isodoubIet Жыл бұрын
@@Tuniwutzi Yeah I can see why someone in a space-constrained environment might want to avoid exceptions, but the rest is largely just FUD.
@sudo_apt_install_youtube
@sudo_apt_install_youtube Жыл бұрын
100% agree with you. I just don't think that comparing Go's error handling to JavaScript isn't fair since JavaScript is 90% bad design and 10% incredible optimization
@martijnvdven
@martijnvdven Жыл бұрын
I am not sure I understand why Primeagen is returning null incase of the error state in the JavaScript function. As he said, when you are calling the function from the outside you must always wrap it in a try-catch because anything can throw and there is no way for you to know. (Or not wrap and accept the consequence of the error travelling up.) Given you must handle thrown errors anyway, why not have the function only declare the happy path return (Promise) and have it always throw on errors? That is what I have been doing.
@kallesamuelsson8052
@kallesamuelsson8052 Ай бұрын
Every time you speak nicely about Go I feel better about my life choices
@aazzrwadrf
@aazzrwadrf Жыл бұрын
The main issue with error handling in Go isn't syntax. It's that the types of errors a function can return are not part of the function signature. You have no idea what errors you're checking for. In a nontrivial program, most nontrivial functions end up propagating a union of unknown errors up the stack, which isn't much better than unchecked exceptions.
@aazzrwadrf
@aazzrwadrf Жыл бұрын
Go isn't Rust. "Errors as values" cannot be implemented well without union types. Having a special syntax for errors would: 1) Allow union types to be added for errors and not the entire language. 2) Go, unlike Rust, has recoverable panics, so the runtime is already maintaining a jump table. Having a special syntax for error handling would allow the happy path to have 0 runtime overhead. Go should adopt something like Zig's error handling.
@isodoubIet
@isodoubIet Жыл бұрын
@@aazzrwadrf Rust also has recoverable panics, they just as you pretty please not to use it. The machinery for it is there, though.
@aazzrwadrf
@aazzrwadrf Жыл бұрын
​@@isodoubIetthe process is, but the thread is not recoverable. Therefore the runtime doesn't maintain a jump table to recover from panics.
@photon628
@photon628 Жыл бұрын
rust error handling is the best error handling I have ever used with result set and question mark operator 👍
@npc-drew
@npc-drew 11 ай бұрын
There is this too: ``` func check(e error) { if e != nil { panic(e) } } func main() { err := ... check(err) value, err := ... check(err) } ```
@sbditto85
@sbditto85 Жыл бұрын
It definitely could be better though and it hurts the scan ability of the code as in it can make it harder to understand the non-error handling code flow. Still things could always be worse…
@jamesprendergast7158
@jamesprendergast7158 Жыл бұрын
The 'idiomatic' way of error handling in Go is to try to align the happy path on the left - if you do that then you can configure your IDE to collapse 'if err != nil{ ... }' blocks so that you only see the non-error case. But TBH the happy path is almost always trivially simple - the more interesting and critical parts of your code will probably be the error handling
@minikindaniil99
@minikindaniil99 Жыл бұрын
Well, error handling has virtually opposing requirements: 1) we want to separeate happy path from error handling 2) if we don't know what to do with error, we propagate it upwards 3) result of a function should always be in a valid state when used as argument to another function So far exceptions look like a good fit, except a) in most languages function signature doesn't show possible exception types; b) it is easy to forget to handle them and it can leave your program in a very undefined state In that sense explicit error return switches its benefits with exceptions On the oher hand Option with its and_then interface looks like an upgrade from both of them
@isodoubIet
@isodoubIet Жыл бұрын
"Option with its and_then interface looks like an upgrade from both of them" It's not an upgrade, it's also a tradeoff. It'll perform worse on deeper call stacks (exceptions can be designed so they're free on the happy path and will have fewer instructions added to return statements), It infects the function return type (so changes on possible errors become 'viral'), and it requires boilerplate that can obscure the business logic.
@pldcanfly
@pldcanfly Жыл бұрын
if err != nil { return err; } is a snippet... and copilot is really good at just suggesting that, so it is not that tedious tbh. And having errors as values let's you do amazing things with how they should be handled, etcpp. I don't get when people say go-error-handling is bad, when in reality it's a great thing to have. It's like saying it is annoying that i have to update the type-definition in Typescript whenever I want to assign another property. Yeah, it's work to do, but it is a good thing that you have to do that.
@patrickaikonia853
@patrickaikonia853 11 ай бұрын
I love the take and I also raw dog my JSON.parse every single time unless I have more than on potential error source
@ybabts
@ybabts Жыл бұрын
Yeah error handling in JS is terrible, which is why i made my own library to make the error handling closer to languages like Rust. Its so much nicer to handle errors as values instead.
@brady1123
@brady1123 Жыл бұрын
The only problem with Go's error-handling is that you're allowed to stuff the `err` result in a bit bucket and ignore it. I wish the compiler would require you to always check the `err` value.
@andreizarra9972
@andreizarra9972 Жыл бұрын
Oh men I totally agree with you because my code in typescript looks exactly like the example that you do with all those try catches for handle all possible errors, I realized that I'm using the wrong language
@xyangst
@xyangst Жыл бұрын
Just don't use exceptions at all
@mattiasmartens9972
@mattiasmartens9972 Жыл бұрын
Wow my error handling is so much more explicit now that I’ve rewritten everything in Go! *Turns around* glad there’s no super-easy-to-trigger primitive runtime construct that bypasses all of it.
@danielsan901998
@danielsan901998 Жыл бұрын
With zig you can use try and avoid all that boilerplate.
@natescode
@natescode Жыл бұрын
Exactly
@capability-snob
@capability-snob Жыл бұрын
If you aren't doing manual resource management - e.g. you have defer/with/using/RAII/Context - there's not many reasons to care which function call failed. Where I handle these differently in Go, I'd otherwise use the type to distinguish cases I can handle from those that I can't. Well done btw, well done 4:30
@juice2
@juice2 Жыл бұрын
I really love this design choice in golang
@aidemalo
@aidemalo Жыл бұрын
Well, equivalent would be not return Promise, but throwing error anyway (even after special handling)
@taylorallred6208
@taylorallred6208 Жыл бұрын
One of hardest pills I’ve ever had to swallow: code aesthetics do not matter nearly as much as code pragmatics.
@aazzrwadrf
@aazzrwadrf Жыл бұрын
go's error handling is neither pragmatic nor aesthetic.
@isodoubIet
@isodoubIet Жыл бұрын
Neither matter as much as expressing oneself clearly, though. When you drop a platitude using a made-up expression like "code pragmatics" which people can only guess at the meaning of, you already failed.
@hakuna_matata_hakuna
@hakuna_matata_hakuna Жыл бұрын
this is the kind of content i loved this channel for
@AlexanderBorshak
@AlexanderBorshak Жыл бұрын
That make sense (if you want to know exact error, of course; if not - just one try / catch is enough); but real problem that Go has MORE than one issue in design: aside of this error handling - poor expressiveness, no first-class support for user defined collections (you cannot use for .. range for own types), half-implemented language abstraction (like when append() cannot take care about underline references so developer should bother with reassigning); unsound type system, non-obvious defaults values for some types (nil for map if we use just var, and empty map if we use make()) - and so on. And most of this flaw because authors of Go decide pick up the _simpler_ way of language / compiler implementation; instead of pick up better language's users experience (i.e. developers experience). Each language have strong and weak points. But Go have a bunch of weak ones. Surely, since Go is Turing complete, it can be used for literally anything, but after language with good expressiveness like JS/TS, Python, Rust, even PHP, the Go looks a bit lame...
@Nobody1707
@Nobody1707 Жыл бұрын
I'd like to think that no one is holding JS up as the ideal reference for any language feature (except maybe generator functions). I'd say the two most recent popular languages with good error handling are Swift and Rust. Go error handling sucks, but JS kinda just sucks generally.
@Maxbl4
@Maxbl4 Ай бұрын
Show me how you handle division by zero in your clean go code lol :) Also, in js your are using await, which does not exist in go. How would you call an async method in go and wait for it's result? How easy it would be? ;)
@lukekurlandski7653
@lukekurlandski7653 Жыл бұрын
I honestly started doing this in Python to some degree when I need more granular control over error handling. Sometimes, I want to handle different ValueErrors differently, and the doing so requires subclassing ValueError with a dozen or so different exception types and its just gets crazy. Way easier to return an error code and read the function’s documentation to figure out what that error code means.
@teleraptor6076
@teleraptor6076 Жыл бұрын
Why not create a single subclass which has the error code as an attribute?
@sda-jf3cc
@sda-jf3cc Жыл бұрын
and go does not even force you to handle it, you can just use _ and move on, when you really really need to move fast I just do err.ifn and autocomplelete writes the rest for me, and err.pri and again autocomplete writes the rest for me. the worst thing in ts is changing your types and including null just because there could be an error, it sucks
@Samuronchik
@Samuronchik Жыл бұрын
In this simple example explicit error handling may be better, but I think realistically it more often not possible to handle error than handle it gracefully. In such cases the error must bubble up, be logged, be traced in telemetry and so on. And any time you add try/catch you make error invisible from the tooling that is in place. It may not be logged, you may not receive and alert and so on. So I strongly believe that try/catch statement should be very justified to be present and most often should be removed. On the other hand with go error handling it is way more difficult to ensure you don't mess with tooling. In this case monadic handling like Error monad is much better. You explicitly handle the success state and let it propagate to caller site to be handled by tooling explicitly so everyone understands that you have this tooling in place. With catching errors using some framework machinery may not be so obvious for all the team. Shotrly put, both approaches sucks, JS way is easier to check, use Error monad if you want, don't handle errors if absolutle sure what to do with them
@Wh4tsupy0
@Wh4tsupy0 Жыл бұрын
I think the lesson of this video is that Go’s error handling is only bad in comparison with languages like Rust and Zig that have better syntax for handling errors, but is still good when compared to languages that don’t use errors-as-values.
@austecon6818
@austecon6818 3 ай бұрын
I just hate the insane level of repetition of writing if err != nil 500 times... They should have added syntactic sugar for this like what Rust has. Then it would be almost the perfect language. The other pain point is lack of generic containers like what Java has built-in (TreeMap, List, Set, Map, ordered maps and sets, doubly linked list, stack, queue, double ended queue etc.)
@hbobenicio
@hbobenicio 10 ай бұрын
Very good point. So when you don't need/want to handle the error, JS way is better/simpler than go. But when you need/want to handle the error, golang is actually better. Agreed. But, I would say that most of the time we are actually raising up the error to be handled higher up the stack (with perfectly fine error handling code). So most of the time golang's way would not be really "pleasant". For me the best selling point in favor of golang's error handling (which I do agree is much better then JS and almost any other language) is the *explicity* of it! Explicit is always better then implicit, IMHO. So it's generally a bit verbose and awkward I must admit but REALLY consistent, explicit and clear on intents. So it reads really really fast and natural to everyone. No misteries or hopes or technical theories about it. An this is why golang error handling is better then most
@michaeldelang9746
@michaeldelang9746 Жыл бұрын
Does typescript not have Option/Result types? That would at least alleviate the return type signature.
@OnFireByte
@OnFireByte Жыл бұрын
There are a lot of library that create Option/Result. But without good pattern matching syntax and you have to wrap all external/built-in function to return Result type instead of throwing, I don't think it's really that good, not to mention the performance cost.
@chigozie123
@chigozie123 Жыл бұрын
As a return type, no. You have to explicitly say `mytype | undefined`. As a property type, yes, you can use `mytype?`.
@xN811x
@xN811x Жыл бұрын
One could use discriminated unions to mimic a Result type: type Result = { type: 'ok', value: V } | { type: 'error', error: E } A function then returns an object where the type attribute is set to either 'ok' or 'error'. You do that so each of your union arms can have a different payload type. On the call side you can check the value of the type attribute in an if-condition and the typescript compiler will automatically narrow down to the correct payload type inside the block. If done correctly discriminated unions are a powerful feature.
@applepie9806
@applepie9806 Жыл бұрын
Love these kinds of videos, I didn't get the controversy until now
@shellderp
@shellderp Жыл бұрын
whats nice in Kotlin is you can do val x = try {} catch { return } and not have a var/val that was ever null
@floppypaste
@floppypaste Жыл бұрын
it boggles my mind, that he never has looked into kotlin
@MysteryJake89
@MysteryJake89 Жыл бұрын
The JavaScript version should probably throw again in the exceptional cases, rather than conflating an error with a null value (which could probably be considered an antipattern). This keeps the return type clean, the caller also doesn't know where it failed either if you simply start returning null in place of an error. Think NodeJS and the error codes that get attached to errors to do error handling with context clues (e.g. ENOENT). Either you know how to handle the error and you do, or you wrap the error with some context, or you just let it flow up.
@dixztube
@dixztube 7 сағат бұрын
Pop quiz. Println - what is the difference between the log and fmt version ?
@ksidharth1994
@ksidharth1994 4 ай бұрын
Why not have a function for await and call it like ```const [ value, err ] = awaited( fetch( API_URL ) ); ```
Golang is BAD for SMART PEOPLE
27:25
ThePrimeTime
Рет қаралды 289 М.
I Made A Game In Two Days | Prime Reacts
14:21
ThePrimeTime
Рет қаралды 62 М.
Jaidarman TOP / Жоғары лига-2023 / Жекпе-жек 1-ТУР / 1-топ
1:30:54
Air Sigma Girl #sigma
0:32
Jin and Hattie
Рет қаралды 45 МЛН
Хаги Ваги говорит разными голосами
0:22
Фани Хани
Рет қаралды 2,2 МЛН
Goroutines ARE USELESS
12:57
ThePrimeTime
Рет қаралды 110 М.
This might fix error handling in JS
33:07
Theo - t3․gg
Рет қаралды 63 М.
are we cooked w/ o3?
13:58
ThePrimeTime
Рет қаралды 68 М.
Why I Quit Netflix
7:11
ThePrimeagen
Рет қаралды 526 М.
Exception vs Errors | Chris Lattner and Lex Fridman
8:02
Lex Clips
Рет қаралды 50 М.
Remote Work Won | Prime Reacts
35:56
ThePrimeTime
Рет қаралды 104 М.
My Initial Impresson Of Go
12:39
TheVimeagen
Рет қаралды 107 М.
Rust vs Go : Hands On Comparison
50:40
ThePrimeTime
Рет қаралды 239 М.
TMUX in 100 seconds | Prime Reacts
11:43
ThePrimeTime
Рет қаралды 178 М.
Jaidarman TOP / Жоғары лига-2023 / Жекпе-жек 1-ТУР / 1-топ
1:30:54