err != nil Is GOOD? (And Why)

แชร์
ฝัง
  • เผยแพร่เมื่อ 25 พ.ย. 2024

ความคิดเห็น • 627

  • @DerekDoes...
    @DerekDoes... 11 หลายเดือนก่อน +128

    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 11 หลายเดือนก่อน +3

      Yup!

    • @manacht2727
      @manacht2727 2 หลายเดือนก่อน +1

      to be fair, prime can turn a 5 minute video in a 40 minute one lmao

  • @nisancoskun
    @nisancoskun 11 หลายเดือนก่อน +382

    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 11 หลายเดือนก่อน

      nice website 👌

    • @amotriuc
      @amotriuc 11 หลายเดือนก่อน +15

      libraries should specify what errors they should the throwing, if they don't it is a crappy library.

    • @mdbk2
      @mdbk2 11 หลายเดือนก่อน +30

      @@amotriuc Or the language is crappy if everyone can just ingore errors.

    • @amotriuc
      @amotriuc 11 หลายเดือนก่อน +9

      @@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 11 หลายเดือนก่อน +4

      @@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 11 หลายเดือนก่อน +193

    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 11 หลายเดือนก่อน +1

      this!

    • @raenastra
      @raenastra 11 หลายเดือนก่อน +1

      agreed - in the big picture, syntax is pretty trivial; what it enables you to do matters more

    • @MomchilAtanasovHome
      @MomchilAtanasovHome 11 หลายเดือนก่อน +2

      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 11 หลายเดือนก่อน +2

      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 11 หลายเดือนก่อน +10

      @@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 11 หลายเดือนก่อน +78

    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 11 หลายเดือนก่อน +6

      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.

    •  10 หลายเดือนก่อน +3

      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 11 หลายเดือนก่อน +108

    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 11 หลายเดือนก่อน +1

      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 11 หลายเดือนก่อน +3

      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 2 หลายเดือนก่อน

      but null !== null

  • @BrianGwaltney
    @BrianGwaltney 11 หลายเดือนก่อน +109

    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 11 หลายเดือนก่อน +9

      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 11 หลายเดือนก่อน

      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 11 หลายเดือนก่อน +3

      OP should not be anywhere near a computer

    • @OnFireByte
      @OnFireByte 11 หลายเดือนก่อน

      @@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 11 หลายเดือนก่อน +6

      @@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.

  • @einargs
    @einargs 11 หลายเดือนก่อน +10

    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.

  • @themichaelw
    @themichaelw 11 หลายเดือนก่อน +61

    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 11 หลายเดือนก่อน +13

      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 11 หลายเดือนก่อน +1

      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 11 หลายเดือนก่อน +3

      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 3 หลายเดือนก่อน

      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 3 วันที่ผ่านมา

      ​@@orterves I never liked Result, (value, error) feels less boilerplaty and more control. Result is just an abstraction of it

  • @amirhosseinsoleimani5410
    @amirhosseinsoleimani5410 11 หลายเดือนก่อน +39

    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 11 หลายเดือนก่อน +5

      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 11 หลายเดือนก่อน +7

      @@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.

  • @Grouloo
    @Grouloo 11 หลายเดือนก่อน +11

    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.

  • @vladislavkovechenkov8473
    @vladislavkovechenkov8473 11 หลายเดือนก่อน +2

    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!

  • @IvanRandomDude
    @IvanRandomDude 11 หลายเดือนก่อน +84

    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 11 หลายเดือนก่อน +3

      Aren't panics way worse to deal with than JavaScript errors?

    • @ThienNguyen-bg1kx
      @ThienNguyen-bg1kx 11 หลายเดือนก่อน

      @@zaneearldufour not if we talking about a panic in http handler with proper recovery middlewares

    • @Gusto20000
      @Gusto20000 11 หลายเดือนก่อน +5

      @@zaneearldufourhow exactly you get panic from val,_ := foo()? Or you think it won’t panic if you write val, err := foo()?

    • @arturfil
      @arturfil 11 หลายเดือนก่อน +19

      @@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.

    • @VivekYadav-ds8oz
      @VivekYadav-ds8oz 11 หลายเดือนก่อน +1

      @@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?

  • @DmitrijKudriavcev
    @DmitrijKudriavcev 11 หลายเดือนก่อน +3

    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.

  • @eNtrozx
    @eNtrozx 11 หลายเดือนก่อน +19

    Yeah but the annoying things is that if you want the error to bubble up, you still have to handle it

    • @ficolas2
      @ficolas2 11 หลายเดือนก่อน +3

      Which is one of the reasons why rust does a much better job, you can just use the question mark

    • @SandraWantsCoke
      @SandraWantsCoke 11 หลายเดือนก่อน

      yes, but you simply return the error

    • @eNtrozx
      @eNtrozx 11 หลายเดือนก่อน +4

      @@SandraWantsCoke That's handling, you write actual code that does that

    • @PamellaCardoso-pp5tr
      @PamellaCardoso-pp5tr 10 หลายเดือนก่อน

      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 5 วันที่ผ่านมา

      When you need errors to bubble up - you have to question your architecture.

  • @mctechcraft7
    @mctechcraft7 11 หลายเดือนก่อน +1

    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

  • @mmmk189
    @mmmk189 11 หลายเดือนก่อน +10

    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

  • @beofonemind
    @beofonemind 11 หลายเดือนก่อน

    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.

  • @LinxOnlineGames
    @LinxOnlineGames 11 หลายเดือนก่อน +2

    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.

  • @dranon0o
    @dranon0o 11 หลายเดือนก่อน +1

    ```
    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`

  • @MatthewAhrensTech
    @MatthewAhrensTech 11 หลายเดือนก่อน +1

    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 11 หลายเดือนก่อน

      Or use Rust and just get both?

  • @theowenmccarthy
    @theowenmccarthy 11 หลายเดือนก่อน +53

    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 11 หลายเดือนก่อน +2

      This is all I want as well. I dream about it

    • @nskeip
      @nskeip 11 หลายเดือนก่อน +9

      Not sure if '?' operator should panic

    • @ja31ya
      @ja31ya 11 หลายเดือนก่อน +8

      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 11 หลายเดือนก่อน +4

      ? 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 11 หลายเดือนก่อน +1

      @@ja31ya exactly

  • @z0n_
    @z0n_ 11 หลายเดือนก่อน +15

    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 11 หลายเดือนก่อน +5

      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 11 หลายเดือนก่อน +4

      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_ 11 หลายเดือนก่อน +1

      @@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 11 หลายเดือนก่อน

      @@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 11 หลายเดือนก่อน +2

      @@z0n_Or either use a transaction system or defer state modification to the final step of an operation where it can’t fail.

  • @little-ghost-rider
    @little-ghost-rider 6 หลายเดือนก่อน +1

    You can just create some wrap function
    So that it returns undefined rather than throw error

  • @JohnNowak-p1g
    @JohnNowak-p1g 11 หลายเดือนก่อน +16

    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 11 หลายเดือนก่อน +6

      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 11 หลายเดือนก่อน +2

      100% agree.
      I also would recommenced to use error monitoring services like Sentry along with logging, they make life a lot easier.

  • @jefersonnl
    @jefersonnl 2 หลายเดือนก่อน

    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.

  • @Fernando-du5uj
    @Fernando-du5uj 11 หลายเดือนก่อน +1

    Thank God, I was waiting for that last "...agen". I thought you will not do it.

  • @ishi_nomi
    @ishi_nomi 11 หลายเดือนก่อน +5

    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 8 หลายเดือนก่อน

      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.

  • @jasonscherer2631
    @jasonscherer2631 11 หลายเดือนก่อน

    I learned how much this makes sense after now doing a golang code base, I love it so much more.

  • @Tobsson
    @Tobsson 11 หลายเดือนก่อน +11

    If err := doSomething(); err != nil {
    Handle error
    }
    Is something I find beautiful. Wish it would work even if a value is returned.

  • @mintx1720
    @mintx1720 11 หลายเดือนก่อน +2

    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.

  • @greendsnow
    @greendsnow 11 หลายเดือนก่อน +40

    I wish there were a single liner error handling with Go, though.

    • @samfelton5009
      @samfelton5009 11 หลายเดือนก่อน +2

      What language has single line error handling and what does it look like?

    • @antongorov5275
      @antongorov5275 11 หลายเดือนก่อน +18

      Kinda like "expect" in Rust?

    • @paulooliveiracastro
      @paulooliveiracastro 11 หลายเดือนก่อน +7

      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 11 หลายเดือนก่อน

      ​@@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 11 หลายเดือนก่อน +12

      @@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

  • @Slashx92
    @Slashx92 11 หลายเดือนก่อน +3

    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

  • @kallesamuelsson8052
    @kallesamuelsson8052 20 วันที่ผ่านมา

    Every time you speak nicely about Go I feel better about my life choices

  • @mementomori8856
    @mementomori8856 11 หลายเดือนก่อน +4

    I LOVE it personally, just deal with your error right away and be done!

  • @dzisonline
    @dzisonline 11 หลายเดือนก่อน +3

    My biggest issues with errors are not mine but library's. Hunting errors in huge libraries is quite tedious.

  • @taylorallred6208
    @taylorallred6208 11 หลายเดือนก่อน +9

    One of hardest pills I’ve ever had to swallow: code aesthetics do not matter nearly as much as code pragmatics.

    • @aazzrwadrf
      @aazzrwadrf 11 หลายเดือนก่อน +4

      go's error handling is neither pragmatic nor aesthetic.

    • @isodoubIet
      @isodoubIet 11 หลายเดือนก่อน +1

      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.

  • @TacticalEntropy
    @TacticalEntropy 3 หลายเดือนก่อน

    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.

  • @PeterBernardin
    @PeterBernardin 7 หลายเดือนก่อน

    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.

  • @rzabcio3
    @rzabcio3 11 หลายเดือนก่อน +1

    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. ❤

  • @rt1517
    @rt1517 9 หลายเดือนก่อน

    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.

  • @romsthe
    @romsthe 11 หลายเดือนก่อน +1

    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 😅

  • @PerfectMakanju
    @PerfectMakanju 11 หลายเดือนก่อน +1

    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)

  • @blenderpanzi
    @blenderpanzi 11 หลายเดือนก่อน +2

    Yeah, I prefer Rust's error handling over Go's.

  • @aaaaanh
    @aaaaanh 11 หลายเดือนก่อน +1

    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.

  • @programaths
    @programaths 11 หลายเดือนก่อน

    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.

  • @aazzrwadrf
    @aazzrwadrf 11 หลายเดือนก่อน +8

    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 11 หลายเดือนก่อน

      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 11 หลายเดือนก่อน +1

      @@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 11 หลายเดือนก่อน +1

      ​@@isodoubIetthe process is, but the thread is not recoverable. Therefore the runtime doesn't maintain a jump table to recover from panics.

  • @makeshiftartist_420
    @makeshiftartist_420 11 หลายเดือนก่อน +1

    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

  • @patrickaikonia853
    @patrickaikonia853 10 หลายเดือนก่อน

    I love the take and I also raw dog my JSON.parse every single time unless I have more than on potential error source

  • @npc-drew
    @npc-drew 10 หลายเดือนก่อน

    There is this too:
    ```
    func check(e error) {
    if e != nil {
    panic(e)
    }
    }
    func main() {
    err := ...
    check(err)
    value, err := ...
    check(err)
    }
    ```

  • @tonyb3123
    @tonyb3123 11 หลายเดือนก่อน +23

    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 11 หลายเดือนก่อน

      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 11 หลายเดือนก่อน +5

      ​@@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 11 หลายเดือนก่อน

      @@superderpyderps ah that's good to know. Thanks for the explanation!

  • @crum--business
    @crum--business 11 หลายเดือนก่อน +1

    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*/)
    }

  • @CodyDBentley
    @CodyDBentley 11 หลายเดือนก่อน

    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
    }
    ```

  • @capability-snob
    @capability-snob 11 หลายเดือนก่อน +1

    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

  • @emilemil1
    @emilemil1 11 หลายเดือนก่อน +10

    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 11 หลายเดือนก่อน +5

      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 11 หลายเดือนก่อน +2

      ​@@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 11 หลายเดือนก่อน +1

      @@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 11 หลายเดือนก่อน +2

      @@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 11 หลายเดือนก่อน +1

      @@gileee What of you have multiple erros that occur whilst your bubbling to the top. How do you catch those?

  • @juice2
    @juice2 11 หลายเดือนก่อน +1

    I really love this design choice in golang

  • @sbditto85
    @sbditto85 11 หลายเดือนก่อน +3

    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 11 หลายเดือนก่อน

      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

  • @andreizarra9972
    @andreizarra9972 11 หลายเดือนก่อน

    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 11 หลายเดือนก่อน

      Just don't use exceptions at all

  • @photon628
    @photon628 11 หลายเดือนก่อน +13

    rust error handling is the best error handling I have ever used with result set and question mark operator 👍

  • @acuteaura
    @acuteaura 11 หลายเดือนก่อน +5

    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 11 หลายเดือนก่อน +3

      Yes, I much prefer error enums like Zig/Odin/Rust. Go's biggest weakness is not having real enums and unions

  • @esser50k
    @esser50k 11 หลายเดือนก่อน +1

    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..

  • @danielsan901998
    @danielsan901998 11 หลายเดือนก่อน +10

    With zig you can use try and avoid all that boilerplate.

    • @natescode
      @natescode 11 หลายเดือนก่อน

      Exactly

  • @hakuna_matata_hakuna
    @hakuna_matata_hakuna 11 หลายเดือนก่อน

    this is the kind of content i loved this channel for

  • @ilushkinz4424
    @ilushkinz4424 11 หลายเดือนก่อน +16

    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 11 หลายเดือนก่อน +4

      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 11 หลายเดือนก่อน +2

      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 11 หลายเดือนก่อน +1

      ​@@marcs9451The stack is not necessarily unwound. It is in most languages but that's because the language designers were lazy.

    • @taatuu25
      @taatuu25 11 หลายเดือนก่อน +1

      @@marcs9451 What's the difference? isn't "unwinding the stack" the same as propagating up the stack?

    • @isodoubIet
      @isodoubIet 11 หลายเดือนก่อน

      @@gagagero Lol what would have been the "non-lazy" choice?

  • @JeffCaldwell-nemo_omen
    @JeffCaldwell-nemo_omen 11 หลายเดือนก่อน

    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.

  • @lighty262
    @lighty262 11 หลายเดือนก่อน

    Writing code while recreating/solving problem while also talking. That sounds like a native speaker of a computer language.

  • @ckpioo
    @ckpioo 3 หลายเดือนก่อน +2

    why is no one talking about how he just ignored .catch?

    • @heronshorts
      @heronshorts 2 หลายเดือนก่อน

      yeah you can use .then and still return your value with only one .catch

  • @chickenduckhappy
    @chickenduckhappy 11 หลายเดือนก่อน +21

    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 11 หลายเดือนก่อน +2

      True. No one actually writes js code like he did in this example.

    • @Slashx92
      @Slashx92 11 หลายเดือนก่อน +8

      ​@@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 11 หลายเดือนก่อน +7

      @@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?

  • @itzhakeretzkdosha6875
    @itzhakeretzkdosha6875 11 หลายเดือนก่อน +5

    Will golang ever go the 'Result' path?
    I'm missing that and union types in GO

    • @OnFireByte
      @OnFireByte 11 หลายเดือนก่อน

      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 11 หลายเดือนก่อน +2

      ​@@OnFireBytenot everyone has to do that - they're compatible

  • @applepie9806
    @applepie9806 11 หลายเดือนก่อน

    Love these kinds of videos, I didn't get the controversy until now

  • @thegittubaba
    @thegittubaba 11 หลายเดือนก่อน

    You have that JS option in golang too, the magic underscore :D

  • @apollolux
    @apollolux 11 หลายเดือนก่อน

    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.

  • @reilandeubank
    @reilandeubank 11 หลายเดือนก่อน

    As a certified Go fanboy that sometimes hates writing an insane amount of “if err!=nil”, this gave me an entirely new appreciation for my favorite language

  • @Sw3d15h_F1s4
    @Sw3d15h_F1s4 11 หลายเดือนก่อน +3

    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 11 หลายเดือนก่อน

      It could have been a lint at least. Typescript's had this proposal for a long time, yet it hasn't been merged.

  • @ithinkimhipster502
    @ithinkimhipster502 11 หลายเดือนก่อน

    Typescript NEEEDS to add a throws modifier

  • @madskaddie
    @madskaddie 11 หลายเดือนก่อน +1

    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

  • @incursion45
    @incursion45 11 หลายเดือนก่อน

    Unpopular opinion the best way to do this is the way they do it in C# and using expressions in the catch

  • @CallousCoder
    @CallousCoder 11 หลายเดือนก่อน

    I always loathed exceptions it’s a sneaky hidden control flow.

  • @mattiasmartens9972
    @mattiasmartens9972 11 หลายเดือนก่อน

    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.

  • @hbobenicio
    @hbobenicio 9 หลายเดือนก่อน

    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

  • @flammea_
    @flammea_ 11 หลายเดือนก่อน +4

    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 9 หลายเดือนก่อน

      no one really knows lol

  • @brady1123
    @brady1123 11 หลายเดือนก่อน

    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.

  • @lukekurlandski7653
    @lukekurlandski7653 11 หลายเดือนก่อน

    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 11 หลายเดือนก่อน

      Why not create a single subclass which has the error code as an attribute?

  • @robertlemiesz7143
    @robertlemiesz7143 11 หลายเดือนก่อน

    With the js example you can wrap them in an allSettled

  • @maximdolina899
    @maximdolina899 5 หลายเดือนก่อน

    please wine for this gentleman

  • @philipp04
    @philipp04 11 หลายเดือนก่อน +1

    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 11 หลายเดือนก่อน

      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 11 หลายเดือนก่อน +1

      "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 11 หลายเดือนก่อน +1

      @@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 11 หลายเดือนก่อน +1

      @@Tuniwutzi Yeah I can see why someone in a space-constrained environment might want to avoid exceptions, but the rest is largely just FUD.

  • @aidemalo
    @aidemalo 11 หลายเดือนก่อน

    Well, equivalent would be not return Promise, but throwing error anyway (even after special handling)

  • @austecon6818
    @austecon6818 2 หลายเดือนก่อน +1

    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.)

  • @ashishalex10
    @ashishalex10 10 หลายเดือนก่อน

    love these kind of videos

  • @beardedgaminghero3143
    @beardedgaminghero3143 11 หลายเดือนก่อน

    Absolutely fantastic apples to apples and oranges comparison.

  • @francis_the_cat9549
    @francis_the_cat9549 11 หลายเดือนก่อน +1

    I think youd be interested in ginger bills article on why odin will never have exceptions

    • @marcs9451
      @marcs9451 11 หลายเดือนก่อน

      prime already did an interview with bill but I think the article would be a great read

  • @ybabts
    @ybabts 11 หลายเดือนก่อน +1

    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.

  • @dimitro.cardellini
    @dimitro.cardellini 18 วันที่ผ่านมา

    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.

  • @felgenh399
    @felgenh399 11 หลายเดือนก่อน

    Preach
    Never really thought of this. Good content

  • @pldcanfly
    @pldcanfly 11 หลายเดือนก่อน +1

    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.

  • @iflux8821
    @iflux8821 11 หลายเดือนก่อน

    Catching someone else’s error is modern GOTO

  • @dealloc
    @dealloc 11 หลายเดือนก่อน +1

    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 11 หลายเดือนก่อน

      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.

  • @duke605
    @duke605 11 หลายเดือนก่อน

    Zig imo has the perfect solution to this. If go implemented it it would still feel gomatic but be much cleaner

  • @noname78520
    @noname78520 11 หลายเดือนก่อน

    I'll like golang adopts vlang error handling, it is option and result but with simple syntax, I know vlang is knowed as vaporware, but the ideas behind its error handling are pretty good

  • @gustavcoetzee5018
    @gustavcoetzee5018 10 หลายเดือนก่อน

    Good thoughts thanks

  • @Im_Ninooo
    @Im_Ninooo 11 หลายเดือนก่อน +4

    I agree, but sometimes it's nice to just not care about handling specific errors and just put a try-catch block in the main function, specially during prototyping.