Go Has Exceptions??

Поділитися
Вставка
  • Опубліковано 26 лис 2024

КОМЕНТАРІ • 205

  • @archlemon
    @archlemon Місяць тому +387

    Panic is what happens whenever someone looks at my code

    • @RogerValor
      @RogerValor Місяць тому

      recover() often implements opening youtube and watching primagen

    • @takinyash
      @takinyash Місяць тому +10

      How do they recover?

    • @oleg4966
      @oleg4966 Місяць тому +25

      @@takinyash That's the fun part: they don't.

    • @oleksiistri8429
      @oleksiistri8429 Місяць тому

      ​@@oleg4966😂😂😂😂

    • @helloworlditsworld
      @helloworlditsworld Місяць тому

      They don’t recover, they refactor

  • @robkom
    @robkom Місяць тому +210

    From the book Learning Go by Jon Bodner: "Using recover is recommended in one situation. If you are creating a library for third parties, do not let panics escape the boundaries of your public API. If a panic is possible, a public function should use recover to convert the panic into an error, return it, and let the calling code decide what to do with them."

    • @blacklistnr1
      @blacklistnr1 Місяць тому +40

      Library creators seem to always run into the weird parts of the language, while the rest of us live blissfully unaware of the problems

    • @sudifgish8853
      @sudifgish8853 Місяць тому +10

      @@blacklistnr1 It's not just that way for lib creators though. If you write a more complex program you will have more or less isolated parts that may not be 100% bug free and may crash at some point in the future. You may not want your whole program to crash in that case, especially a server. The "public facing" function of such a part of your program should always return an error instead of throwing a panic. The only time you should not recover and let the program crash is if the panic makes the program actually unusable.

    • @disieh
      @disieh Місяць тому +2

      IMHO this is a fun side-effect of C ABI being the only way two languages can interop. C doesn't know exceptions so hence everything you expose to an API that can be used by C, it must catch every single exception (or exception-like) that can possibly happen, make sure stack and heap are not clobbered and report the error in a C-like way. Part of the reason why C++ is so unbelievably complex is because it needs to deal with this constantly.

    • @metaltyphoon
      @metaltyphoon Місяць тому

      This is all because you cant recover from a go routine your code didn’t start it.

    • @Rgotto2
      @Rgotto2 Місяць тому

      Thank you!

  • @Denominus
    @Denominus Місяць тому +9

    Common use for recover in Go is in web servers/message queue processors. Null references, index out of range panic bugs would cause the entire web server/consumer to crash. You don't want that, especially if its a panic isolated to specific a user/message. So you will typically have a recover in your global middleware somewhere to prevent the panic escalating all the way up the stack and into a crash.

  • @yidisprei100
    @yidisprei100 Місяць тому +53

    So this isn't completely accurate. Whenever prime would talk about panics in go, he would talk about it as an intended crash behavior. And he's right about all that there probably shouldn't be a way to recover from intended crashes. However, panics can also happen unintentionally for example when trying to dereference a nil pointer, accessing a non existing index in an array, or division by 0. That's something that typically shouldn't happen and it's a core error in the code. That being said, it's probably a good thing that echo (or any other, or even custom) web server has a way to recover from that and not crash the entire server because one handler has some faulty code. It probably is a good thing that you can catch that and possibly do some logging for it and return a 500 rather than crashing the whole program.
    Another thing worth mentioning is that if go didn't have a method to recover from panics, it could create an attack vector where hackers would try to exploit web servers by creating a panic (many ways to do this) and instead of just getting a 500, they would crash the whole server. This becomes even more likely if you are going tiger beetle and using asserts in production.
    Recover is also built to work very differently than try/catch. It doesn't return the error type and you can't have different behavior based on what kind of error (panic) happened. It just allows for continuation after a panic happened and then do something about it knowing that a panic happened. I am not saying that it's impossible to use it in a try/catch pattern but it certainly isn't easy to use it in that way. The best way to work with errors in go is as values, as intended. The recover functionality doesn't go against that.
    Btw love prime and have learned a lot from your videos!!

    • @javierflores09
      @javierflores09 Місяць тому +3

      I honestly don't understand the last part, at least in Java, you throw a new exception (aka panic), then it unwinds the stack, and it recovers if we hit a try while unwinding the stack, the catch does essentially what the defers would do given you remembered to, but if there is no try then the program just crashes. The only difference in behavior here is that Go lets you do the cleanup on the use-site by leveraging defers, but as far I can see this is your run-of-the-mill exception.
      edit: if I were to point a more clear difference, it would be a cultural one. try-catch isn't discouraged in Java, it is part of the control flow after all, so it means that unlike in Go, people use it willy-nilly without understanding the implications, which leads to the whole set of issues that is nobody doing proper cleanup in the catch (or finally actually, but nobody uses finally)

    • @MrLinusBack
      @MrLinusBack Місяць тому +4

      This! It would otherwise be very har to build any kind fo system that is supposed to continuisly live forever, imagine building a database in go without being able to recover from panics.

    • @yidisprei100
      @yidisprei100 Місяць тому +2

      @@javierflores09 I suppose you're right. It's mostly the cultural side. Go doesn't encourage the use of try/catch for standard control flow. Also the panic/recover system is very different than the standard try/catch in js and python mostly due to how they are built with different exception types and all that.
      In theory it's possible to ignore go's intended usage and rely just on try/catch or panic/recover as we'd call it in go but it would be a pretty difficult thing to do unless you intentionally use the errors as values system and explicitly call panic when encountering an error value. In that case, you are going way out of your way to not work with errors as values

    • @voskresenie-
      @voskresenie- Місяць тому

      ​@@javierflores09​@javierflores09 ​The difference is that typically a recover is done to translate a panic to a standard error, where the request still fails but fails gracefully, whereas a try/catch is often done to use a fallback and log the error but otherwise continue execution.
      In theory, yes, you can use a panic in the same way as an exception, you can even have custom panic "types" with the arg to panic(). It any language with whiles and fors, you can use a while to execute a for-style loop, and you can use a for-loop to execute a while. You can also use a string to store an integer, too, and multiply going char by char and matching 0-9. And you can return every value an a class with members of return type and a custom error type. But that's not how those things are designed. Every programming language is equivalent to every other programming language in capabilities, more or less, if you are willing to use features of the language in ways they're not designed to be used. But most people follow the patterns of a language, and those patterns distinguish the features of those languages. If you use panic() in the way exceptions are used in Java, for example, you are using the language wrong.

    • @AdroSlice
      @AdroSlice Місяць тому +7

      It basically boils down to these valid use cases:
      - Use panic if you want your goroutine (and by extension the entire program, thanks for the note) to crash. Don't combine it with a recover.
      - Use recover if you want to guard against an unexpected crash resulting from a logic error, notably at package boundaries
      It's panic OR recover. Not panic AND recover.

  • @Ayssi-purple
    @Ayssi-purple Місяць тому +4

    I only used recover once, it was for an encoder/decoder that used a lot of reflection. With Go reflection, the compiler won't stop you from doing something stupid, and EVERYTHING panics. Usually I wouldn't recover from implementation mistakes but in context it made sense to put a little defer recover block at the top of my function so I could return an error.

  • @awesomedavid2012
    @awesomedavid2012 Місяць тому +9

    I'd say the big difference is what the stack overflow post said, with try catch, you can run code in a function both when there is an exception and when there isn't. It's just the code directly underneath.
    With recover, it only runs the code in the defer and then ends the function.

    • @suede__
      @suede__ Місяць тому +1

      It will end the function and run all defers.

    • @AdroSlice
      @AdroSlice Місяць тому +2

      Try = any function that contains or calls code that may panic
      Catch = the logic after recover
      Finally = all defers
      The main upside of gos approach is that you dont need to check what you have to clean up in your "finally", because it is only tacked on as a defer if it worked in the first place. Apart from that, panic AND recover have about the same semantics as throw and catch. But you should ignore those similarities and see it as panic OR recover, as you should only explicitly panic if you want to crash, and you should only recover at package boundaries or if there is a chance of a language-caused panic, such as a divide by zero.

  • @Daniel_Zhu_a6f
    @Daniel_Zhu_a6f Місяць тому +73

    rust has exceptions too. you can catch panics

    • @scheimong
      @scheimong Місяць тому +21

      Shhhhhh! Don't let them know

    • @juh9870_projects
      @juh9870_projects Місяць тому +26

      Rust doesn't guarantee any panic would get caught, making it unreliable in practice and more of a debug tool, and you can easily make all panics abort

    • @xslashsdas
      @xslashsdas Місяць тому +5

      I can also catch panics irl, it's not fun

    • @timseguine2
      @timseguine2 Місяць тому

      @@juh9870_projects And with C++ you can also easily make all exceptions call terminate with a single compile flag. So with that logic C++ doesn't have exceptions.

    • @giacomostevanato2203
      @giacomostevanato2203 Місяць тому

      @@juh9870_projects It is used in practice though. Web frameworks often use it to return HTTP 500 errors instead of shutting down when an endpoint handler panics, and there are even libraries like salsa that exploit them for weird stuff (e.g. in salsa for cycle recovery)

  • @thomashabetsse
    @thomashabetsse Місяць тому +4

    The reason it matters that go has exceptions is that even if you don't use them, you *still* have to write exception safe code.
    E.g. that defer unlock isn't just neat syntax, it's mandatory.
    And if you say it doesn't have exceptions, people think it's just syntax.
    Also, printf printers and go standard web server swallows exceptions.

  • @michinorobotto
    @michinorobotto Місяць тому +8

    Meanwhile hardcore Python developers, trying to make sense of a two-page try/else statement in a 3rd party library with 65 stars on GitHub that hasn't been updated in 6 years...

  • @marcoceriani1069
    @marcoceriani1069 Місяць тому +3

    A clarification on echo: recover is not the default behaviour, it's an optional middleware that we can add to the server. So we have the option to let the server crash, or hope that the panic only impacted a single goroutine (i.e. a single request) and has no other side effects.
    Let's say you have a bug, or a missing validation in your input, which causes the allocation of 8GBs of RAM in a single go, but your machine/container doesn't have that much memory. Do you prefer to crash the entire server, or just that goroutine? Probably it depends case by case.

  • @XKCDism
    @XKCDism Місяць тому +6

    What is a panic if not an unhandled exception in the program?
    If the exception is unhandled of course a crash happens.

    • @Excalibaard
      @Excalibaard Місяць тому +2

      "We'll stop panicking later" sounds scarier than "we'll handle the exception later"?

  • @k225
    @k225 23 дні тому

    That's like saying the Amiga "Guru Meditation" screen and Windows 95 "Blue" screen were Exceptions because the user could continue and "recover" from the panic

  • @Ayssi-purple
    @Ayssi-purple Місяць тому +1

    About the difference in control flow brought up at 6:29, you can use panic/recover like a try/catch block very easily by wrapping it in a function (5~10 lines), Prime even reacted to an article at some point about someone arriving in a new codebase and finding exactly that 🤢.

  • @manuel_g_g
    @manuel_g_g Місяць тому

    12:00 🎯 Rust for functions without state, Go on top of that handlining stateful stuffs and communication process (orchestration). It's a good combo. For example: Rust as lambda functions, Go as Event Bus or Message Broker of the functions.

  • @vytah
    @vytah Місяць тому +7

    So if I understand it correctly: defer is like catch+finally all in one, but written before the throwing code, not after like in other languages, and recover() returns the caught exception, or nil if there's none.

    • @3DArea
      @3DArea Місяць тому +2

      defer executes always in go (good or bad behaviour), catch in other languages doesn't. You can panic() and a defer will execute as well

    • @tomsmith6513
      @tomsmith6513 Місяць тому

      @@3DArea "defer" does what the "finally" block does in C#. My question would be . . . (as someone who hasn't gotten into Go yet), what if you have a "return" statement before a "defer" statement? You said "defer executes always." What if it returns before the end?

    • @jack-d2e6i
      @jack-d2e6i Місяць тому +1

      @@tomsmith6513 Statements execute in lexical order. If an early return is executed prior to a defer then that defer won't be executed.

    • @MrLinusBack
      @MrLinusBack Місяць тому +1

      @@jack-d2e6i Yes, except if you have multiple defer statements, then they are executed in reverse first in first out principle.

    • @anywaylose3999
      @anywaylose3999 Місяць тому +2

      Well, basically deffer is just finally block, but for a whole function, and you can have multiple deffer's in one function

  • @BloodEyePact
    @BloodEyePact Місяць тому

    The simplest way to understand it is that you recover when two criteria is met:
    1. You are calling code that you are not responsible for that might panic
    2. Between the defer'ed recover and the end of the defer-ing function, nothing can occur that could the state of that function.
    Recover acts as a "checkpoint", anything above it in the call stack is the wild west, but anything below must be insulated from it. The web server is the classic example, it can be certain that nothing a handler function can do can disrupt it or corrupt it state, but that code is coming from an outside source, so it defers a recover that handles a panic by logging it, writing a 500 status code, and then cleaning up the connection and going on with its life without impacting other handlers that are running concurrently or preventing new connections from being accepted.
    On the flipside, there's also basically only one situation in which a panic is justified, and its when you aren't allowed to return an error, but have nothing else valid to return.

  • @suede__
    @suede__ Місяць тому +1

    5:15 Go has this for certain things like a concurrent map write or unlocking an unlocked mutex are fatal errors that can't be caught by a recover as opposed to a panic for the exact reason listed for Zig.

  • @konstantingeyst4568
    @konstantingeyst4568 17 днів тому

    Recover is okay if the code may throw, say, index out of range, and you don't want to crash the entire thing. You catch it, log it, and proceed. Say, a user sent a crafted request that broke some code, you don't want your server to be down for all users

  • @keybraker
    @keybraker Місяць тому +1

    It's nothing like try catch, recover only exists if you can save the panic.

  • @hooch912
    @hooch912 Місяць тому +10

    A panic in a go routine will crash the entire program. That makes for an extremely poor server implementation. This leads to an interesting design question. Is it better to fail fast or try to be as resilient as possible. I tend to choose the latter.

    • @User948Z7Z-w7n
      @User948Z7Z-w7n Місяць тому +7

      Crash fast but locally. Make some boundary

    • @tomsmith6513
      @tomsmith6513 Місяць тому +1

      It depends if a single recover() call can stop the panic, a recover() call followed by a return statement or just a return statement, after which it executes all defer statements up to the panic. There must be some protocol for stopping a panic.
      If so, then calling panic() again would be equivalent to "rethrowing" an exception.

    • @voskresenie-
      @voskresenie- Місяць тому +1

      that's basically the prime use case for 'recover'

    • @avwie132
      @avwie132 Місяць тому

      Fail fast, like erlang.

    • @spl420
      @spl420 28 днів тому +1

      CLI - crash immediately.
      GUI - crash if you're not sure you'll recover.
      Server - give client an error and return from goroutine, main process never crashed. Would love if there'd be a way to crash goroutine without crashing app like in elixir, but gotta work with what we have.

  • @xarz3
    @xarz3 29 днів тому

    Panic/recover is how you should code a resilient server in go that handles traffic using goroutines.
    1. Accept a connection and spin up a goroutine to handle it.
    2. At the top of the goroutine stack add a defer/recover to trap panics, log, emit metrics and gracefully return a server error.
    3. Then go on and implement all logic using the go errors, never ever use panic.
    This way if a panic happens (eg out of memory, unmanaged divide by zero or other stuff that panics but doesn't return an error) it is handled gracefully at the top without crashing. All other errors are managed where they happen

  • @VictorCaldo
    @VictorCaldo Місяць тому

    The architectural pattern you refer to in 12:13 is called "Pipe and Filters" and it's the one Unix shell CLI tools use (echo | and all that goodness). So you're saying that Rust is really good for writing filters. This is super insightful I'm glad Lex asked that question. I just learned about these things from a 1994 paper "An Introduction to Software Architecture" by Garlan and Shaw. Might be an interesting read for you @prime

  • @npc-drew
    @npc-drew Місяць тому

    The name: "I wanna see Lex and Prime in a stream together"

  • @TheDuckPox
    @TheDuckPox Місяць тому +1

    Most of the times you cannot fully control other people's code (or even your own code) under a web server. It might be due to nil pointer dereference or just somebody putting panics for things they don't want to handle. It is better to catch the panic, recover and log the error (urging somebody to fix it instead of ignoring it), while other people do not have to experience any unnecessary downtimes.

  • @Ayssi-purple
    @Ayssi-purple Місяць тому +4

    Important to note: recover only works for the CURRENT GOROUTINE, if you panic in a "child" goroutine your defer function will not be called, and you won't be able to recover. The child goroutine will panic, and then the whole program will panic. This makes recovers even less useful imo.

    • @Ayssi-purple
      @Ayssi-purple Місяць тому

      btw Rust panics and panic propagation work very differently afaik

    • @tomsmith6513
      @tomsmith6513 Місяць тому +1

      If a goroutine is a separate thread (I got this from a quick web search), then that could happen in any language. You would just have to handle the "error" or "exception" in that thread and find a way to convey the information to the calling thread. You would have the same problem in C# if a thread throws an exception and then terminates . . . I can't remember if, the last time I had to catch an exception in another thread, if it brought down the entire C# program. It's been a while, but this wouldn't be a problem unique to Go. You just have to get your "exception handling" code right.

    • @nafaidni
      @nafaidni Місяць тому +3

      This is why it pays to have a wrapper around spawning Goroutines that captures panics and wraps them with errors, which when awaited by the parent thread will propagate either as panics or errors.

    • @spl420
      @spl420 28 днів тому

      ​@@tomsmith6513 It's not technically a thread. It's what called green thread - you just give function to a runtime and it executes it whenever it got a free thread.

    • @tomsmith6513
      @tomsmith6513 28 днів тому

      @@spl420 it sounds like what happens in .NET (particularly WPF, which I've been using), where you have a dedicated thread processing GUI events. Once it's finished handling one GUI event, it processes the next, on that same thread.
      As far as I know, .NET threads you create are always somewhere in your application code, until they terminate. They are never left with "nothing to do."
      It sounds like Go has threads that are idle, not pointing to application code, just waiting for something to do, like a lambda function.

  • @Oler-yx7xj
    @Oler-yx7xj Місяць тому

    I remember trying to understand what errors can a Scanf return, and the way the errors are handled there is not just panics and recovers, but a recover hidden within a deferred function, iirc. So, yeah, Go standard seems to be into that kind of stuff

  • @SamualN
    @SamualN Місяць тому +2

    9:09 you could think of it as Go' `try` is always implicit

  • @PJacksonLink
    @PJacksonLink Місяць тому +2

    It would be fun to see a reaction to the "Land of Lisp" music video.

  • @andythedishwasher1117
    @andythedishwasher1117 Місяць тому

    To get the same behavior as a catch block, you would have to make your panic the last thing in the function. Any code you wanted to run after the potentially panicking code regardless of whether or not it panics (i.e. after the catch block) would need to go in a separate function that was called with defer prior to the panic. It is possible, but unwieldy and not idiomatic.

  • @gameprogramme
    @gameprogramme Місяць тому

    I don’t like panics in Go.
    That said, I have found panics as flow control helpful for modeling exits in tests.
    Also, FYI, you can only call `recover()` within deferred code, and `defer` acts a bit like “finally” in more conventional exception languages.

  • @eugeneponomarov7429
    @eugeneponomarov7429 Місяць тому

    Whoa! This is the first time I see Prime is reading UA-cam chat!

  • @Sameer.Trivedi
    @Sameer.Trivedi Місяць тому

    Highlight the first and last letters already, I can't unsee it now.

  • @danser_theplayer01
    @danser_theplayer01 Місяць тому

    In a javascript try catch block will run even after it throws the error up the chain of command. I'm pretty sure you can try{}catch(e){throw e}finally{ // do whatever you want }. I know for certain that you can *return* out of a function with a try block and *immediately after* run the finally block.

  • @rohitaug
    @rohitaug Місяць тому +2

    I'm not a go developer but it seems like recover is just there to do something extra if a panic has occurred. Like, log information to a file before crashing the program. Apparently, panic only runs the deferred statements as it unwinds the stack so it's mostly just running cleanup code. Using recover to resume normal execution from there seems wild and I doubt anyone would actually do that when they could use errors instead.

    • @PassifloraCerulea
      @PassifloraCerulea Місяць тому

      If one goroutine (thread) panics (including bugs like a null pointer dereference, not just explicit calls to panic()) without recovery, your whole program crashes. Web servers for example usually launch a new goroutine for each individual request then do all processing inside a recover(). If something in the request processing causes a panic, it will be caught and the server can respond with a 500 error instead of killing the whole server process and losing all other in-flight requests. If Go had a way to recover from crashes in another goroutine, you could do clever and awesome things like Erlang (only read about it, never used it myself).
      What was always controversial was using panic&recover to handle errors in a deeply nested call tree with lots of trivial errors and error propagation, the classic example being a recursive-descent parser. As far as I know, panic/recover works Just Fine there, but is usually considered bad style even if it would save considerable numbers of if (err != nil) return err; lines (upwards of half the code).

    • @spl420
      @spl420 28 днів тому

      Recovers used that way, for example in CGo projects you gotta use it for C interop. Also having recover in library to return errors isn't uncommon.

    • @PassifloraCerulea
      @PassifloraCerulea 28 днів тому

      Wow. Really cool getting a notification for a comment that now appears to be hidden... Gotta rub it in your face, don't they?

  • @Jarikraider
    @Jarikraider Місяць тому +1

    Remember, you can't crash if you wrap your entire program in an exception.

  • @sergrojGrayFace
    @sergrojGrayFace Місяць тому +1

    7:01 - That's wrong. defer is exactly the same as try-finally, but reordered so that it doesn't increase indentation level of whole code (good).

  • @alexisfibonacci
    @alexisfibonacci Місяць тому

    C# has some like how go handles panic/recover. But the syntax is different.
    in C# you instantiate a new object with "using" analogous to different. This is syntactic sugar to the compiler which now rewrites it as try { ... } finally { ... }. So there is no catch, but the finally block does cleanup ie call the IDisposable.Dispose() method to ensure cleanup of resources.
    So the language is expressive enough to allow you avoid using try ... catch (if your shop prefers returning (value, error) tuples) but still benefit from the try .. finally mechanism to ensure resource cleanup before existing the function.

  • @Hellbending
    @Hellbending 29 днів тому

    X-prime- on the Hub now!

  • @Stimpy194
    @Stimpy194 16 днів тому

    I suppose with "Rust book on ownership" he's referring to Chapter 4: Understanding Ownership from The Rust Programming Language

  • @gautamdey4509
    @gautamdey4509 Місяць тому

    Panic/Recover has always had the same semantics since at least since I've been using go (since 0.9). Recover, also, does not catch all panics. In my experience out of memory errors can not be recovered. I've even ask for it a while back, and the reasoning makes sense. But made it harder to implementing de/serializing things that say they have a set amount of items but the actual number of items is way more, or way less. (rant about how nice it would have been to have an arean alloc here....) The main reason to use recover is for task runners and servers, where you spawn off go routines and they may encounter unrecoverable errors but you don't want to crash the whole program, just crash the go routine, and recover by restarting or logging the issue.

  • @a6b59ghj51d
    @a6b59ghj51d Місяць тому

    What happens when you call throw without catching it? An unhandled exception error which will crash the program... So create a function alias in Golang called throw which calls panic. Further, what's the difference between logrus.Fatal and logrus.Panic?

  • @RomanAvdeevX
    @RomanAvdeevX Місяць тому

    Hi, Prime. What do you think about expulsion of Russian maintainers situation in the Linux kernel?

  • @Kane0123
    @Kane0123 Місяць тому +38

    They are just copying C#... just accept that C# is the best and move on.

    • @FlanPoirot
      @FlanPoirot Місяць тому

      I accept that you're mentally impaired

  • @Diego-Garcia
    @Diego-Garcia Місяць тому

    Just to remember... recover catches nil pointer deference, not just panic()s.

  • @meryplays8952
    @meryplays8952 Місяць тому +1

    Panic recover is a pattern when you run something that either succeeds or fails. You mark it as "something that can fail" and when it fails it does not bring you down. This is not an exceptional situation, but a possibility. It panics, you recover, sort of RPC! What panicsis something that your operation does not depend on!!! If you recover from your panic, you recover to an illegal state.

    • @wilkesreid
      @wilkesreid Місяць тому

      You only recover to an illegal state if the way you choose to use panics is to represent an illegal state. If you use panic/recover just to indicate a function error, then the resulting state is expected. I personally think it’s nice to use panic/assert to always indicate “this should never be the case” and always exit the whole program

    • @JulianBG
      @JulianBG Місяць тому +1

      in many places panic/recovery is used in the same manner "global exceptions handling" in Java/Spring, or when you need some special transactional logic.

    • @meryplays8952
      @meryplays8952 Місяць тому

      @@JulianBG I agree, but this is not the only use case, there is room for "other" uses.

    • @meryplays8952
      @meryplays8952 Місяць тому +1

      @@wilkesreid If you use panic/recover just to indicate a function error then you have a performance penalty. Apart from the risk that defers do not run.

  • @mrobinson9297
    @mrobinson9297 Місяць тому

    ive run into this in production. pass null characters to programs written in go that dont have a catch all will cause some of them to throw exceptions, when they arent written to catch this as an exception.

  • @hyperthreaded
    @hyperthreaded Місяць тому +1

    Forever lockalock.

  • @ukaszdrozdz6200
    @ukaszdrozdz6200 Місяць тому

    Using go I once had a perfectly legitimate usecase for panic recovery: calling an external parser that sometimes panicked on some invalid input. From my POV all I wanted was: you can't parse that? Just give me an error without exploding.

  • @Qrzychu92
    @Qrzychu92 Місяць тому +4

    I guess being able to catch panics is crucial for things like webservers. Division operator does not return result, err (and it shouldn't IMO), so it would be stupid to crash the whole HTTP server if division by 0 happens. Yes, you can tigerbeetle it with assertions and add an if check for zero value, but would you do it absolutely everywhere? The divisor can be a result of some other operation, so it's not that simple to do without perf degradation (hot path being branch free etc), so having the option to panic and not crash the whole thing, just one request is nice

  • @jackof4ll
    @jackof4ll Місяць тому

    It's been two years watching Prime and still for some reason that even i can't find answer to, I keep looking at the one character from start and end that Prime doesn't select.
    Can someone tell me what is it?

  • @JohnDoe-np7do
    @JohnDoe-np7do 29 днів тому

    So effectively panic(any) without any recover(void) {...} crashes or is the equiv of [std::]abort(void) | assert(!true) but we can use recover() to "catch" or in this case, recover the "thrown" value returned by a call to panic() to ensure the program does not crash at runtime provided the call to recover() occurs after a call to panic()? (since its deferred in this case)

  • @00jknight
    @00jknight Місяць тому

    Note: even a "null ptr dereference" is a panic. We use recover to catch bugs, not expected errors. There are cases where "this API call failed, but the whole server can just panic/recover and then accept new API calls"

    • @a6b59ghj51d
      @a6b59ghj51d Місяць тому

      Incorrect. That's a segfault which can't be recovered unlike a panic which is simply an Unhandled Exception

    • @00jknight
      @00jknight Місяць тому

      @@a6b59ghj51d No. You are 100% wrong. Go and try it.

    • @00jknight
      @00jknight Місяць тому

      @@a6b59ghj51d You are 100% wrong. Derefencing a nil ptr in GoLang causes a panic which can be recovered from. Same with accessing an array out of bounds and failed type assertions.

  • @dazoedave
    @dazoedave Місяць тому

    I would prefer panic over log.Fatal. because panic can be handled and panic also allows defer calls to run. where as log.fatal will instantly exit the program and does not allow defers to run.

  • @DustinMowcomber
    @DustinMowcomber Місяць тому

    Actually if a Goroutine panics then the whole process exits. It’s not isolated to the Goroutine. That’s why it’s important to write tests and prevent panics from ever happening.

  • @nexovec
    @nexovec Місяць тому

    Oh no, go has exceptions, time to panic. We might recover though.

  • @SalvatorePellitteri
    @SalvatorePellitteri Місяць тому

    if the panic came from a library I use maybe I want to handle it, recover the panic is the only way to manage it without restart the program

  • @Silencer1337
    @Silencer1337 Місяць тому

    Go error = Java checked exception (environment error)
    Go panic = Java runtime exception (programming or hardware error (i.e. logical error))

  • @sturdyfool103
    @sturdyfool103 Місяць тому

    in my codebases a panic is "I cannot recover so I just need to crash"

  • @TheSulross
    @TheSulross Місяць тому +1

    Was this intended to make Go programmers feel good or bad ?

  • @alienm00sehunter
    @alienm00sehunter Місяць тому

    I think recovering panics is ok on thread or tasks boundaries. Also on a server I think recovering and sending a 500 is ok.

  • @DylanMatthewTurner
    @DylanMatthewTurner Місяць тому +1

    Prime, you should do some Odin

  • @RandomGeometryDashStuff
    @RandomGeometryDashStuff Місяць тому

    00:38 calling function with no arguments and accessing variable is exact same syntax in pascal btw

  • @salvatoreshiggerino6810
    @salvatoreshiggerino6810 Місяць тому

    Conventional wisdom says if you're a web server, recover, don't crash the whole process and take down every other user. But is it as good of an idea as it sounds? In my experience it only breeds complacency and tolerance for runtime exceptions and sloppy code, as well as wearing out the poor on-call staff trying to pick out real high impact issues in a flood of trivial ones.
    On the other hand I haven't worked with the opposite approach, so I don't know if it's better in reality.

  • @complexity5545
    @complexity5545 28 днів тому

    Modern programmers are absolute insane.

  • @8roma8
    @8roma8 Місяць тому +1

    Changing the name does not change the behavior

  • @danielbengtsson9833
    @danielbengtsson9833 Місяць тому +1

    Yes...yes it does.

  • @jameslay6505
    @jameslay6505 Місяць тому

    panic/recover feels more like trapping SIGSEGV in C.

  • @kasvith
    @kasvith 23 дні тому

    panics in golang is a pain

  • @00jknight
    @00jknight Місяць тому

    Our go API recovers if the function panics so it doesn't bring the whole server down. Makes sense to me.

  • @klex3905
    @klex3905 Місяць тому

    "Panic and recovery" it's an oxymoron. Don't do it, certainly don't rely on it. Even if the language supports and promotes it. Stand your ground. Something panicked you SHOULDN"T recover.
    Scoped exceptions are fine. But I'm so tired of people trying to do things with them, I see it a lot in C# project I need to work with. They use finally like a standard library method.

  • @RickYorgason
    @RickYorgason Місяць тому

    If Go is so good, why isn't there a GOTO?

  • @stevefan8283
    @stevefan8283 Місяць тому

    So golang panic is more like longjmp/setjmp...amirite?

  • @3DArea
    @3DArea Місяць тому +1

    This is just semantic masturbation from Loris. Go doesn't have exceptions. It's like calling Go dynamically typed language because you could use interface{} everywhere and then use reflect package to assign values later. I mean, nobody stops you from doing that, but it doesn't make it a dynamically typed language!
    It will be nice if Loris focus more in creating Zig projects and learning materials and less about comparing Zig with other languages over and over.

  • @meryplays8952
    @meryplays8952 Місяць тому

    Terrifying!!! I have seen an open source "codebase" that uses this because this is how M$$$$ does it with SEH!!!

  • @nexovec
    @nexovec Місяць тому

    Oh, if you have a server does 10KRPS and one of your 700 endpoints triggers a panic once, it's maybe not the best idea to crash the entire thing. I mean you could restart the program, but that might take time, it might be misconfigured etc. This way the entire thing stays on the application layer.
    But if you like to watch the world burn, you do you. Maybe it's better, you reduce all the faulty states you might get into when recovering.

  • @thewhitefalcon8539
    @thewhitefalcon8539 Місяць тому +1

    obviously. This is obvious as soon as you hear about recover.

    • @ghdshds1899
      @ghdshds1899 Місяць тому

      No, because you do have to do some mental gymnastics to actually reconcile it with exceptions as they are commonly understood in the world of Java, for example. It's not the same. If you watched the rest of the video before commenting you'd have realised!

  • @YourConsole
    @YourConsole Місяць тому

    It's actually not used in the parsing code anymore

  • @PJacksonLink
    @PJacksonLink Місяць тому

    Wait 'til you see the error recovery in ANSI Common Lisp.

  • @danser_theplayer01
    @danser_theplayer01 Місяць тому

    Skill issues. In javascript all strings are String() so I don't even have to do anything to get say the 3 letter in a string like ("asmodeus")[2], pretty sure I could even do ("hotdog").split("t").join("es ").

  • @theevilcottonball
    @theevilcottonball 3 дні тому

    Rust has exceptions too then, right? Catch unwind anyone?

  • @mind.journey
    @mind.journey Місяць тому

    I use PHP and hate magic __get & __set. I'd rather just call a function, so it's clear that I'm not merely accessing a property and that something is happening under the hood

    • @yjlom
      @yjlom Місяць тому

      on the other hand it's sometimes useful to be able to change representation without breaking everything downstream
      but that's the only sane usecase

  • @jarretthorton7439
    @jarretthorton7439 Місяць тому +2

    One view and 50 seconds? Prime fell off.

  • @himalczyk258
    @himalczyk258 Місяць тому +3

    Omg, a Prime and Lex podcast ep coming ? That would be HUGE, Lex, sir, please make it happen!

  • @w-a-v-3
    @w-a-v-3 Місяць тому

    D MENTIONED!

  • @digiryde
    @digiryde Місяць тому

    This feels more a like a sql error trap.

  • @Kapendev
    @Kapendev Місяць тому +1

    D looks interesting.

  • @mulllhausen
    @mulllhausen Місяць тому

    11:00 Go regexes don't even have negative lookaheads

  • @albizutoday2754
    @albizutoday2754 Місяць тому

    I knew it! Zig is wke too!

    • @dranon0o
      @dranon0o Місяць тому

      Alas, what isn't nowadays

  • @omri9325
    @omri9325 Місяць тому

    Go exceptions are simple, there's no "catch" :)

    • @tomsmith6513
      @tomsmith6513 Місяць тому

      I sort of get it. The recover() thing is not a "catch." You still have to check the return value of recover().
      The advantage of the try-catch block is that you know you have an error. You don't have to check. It's like compile-time type-checking, it's a kind of "software interlocking" that prevents an inconsistent state from happening, where YOU don't need to check for a discrepancy in your code, the language does it FOR YOU. The language itself relieves you of the responsibility of avoiding mistakes.
      The error-handling philosophy (vs exception handling) suffers from the same problem as C++ templates (in contrast to generics in other languages). It's where the language puts the responsibility on you to get things right.
      The explicit and verbose error checking at each step introduces multiple points of failure that you have to vigilantly guard against.

  • @victorian1707
    @victorian1707 Місяць тому +1

    wrt = with respect to

  • @akshaysrivastava6382
    @akshaysrivastava6382 Місяць тому

    I just got clickbaited.

  • @JulianBG
    @JulianBG Місяць тому +1

    This is not right ua-cam.com/video/DYxWnXOn3g8/v-deo.html independently whether you use recover within defer, other defers will execute (i.e. to unlock) or even if you "re-throw" with panic inside defer recover function, it will still execute the other defers on the stack!

  • @broccoli-dev
    @broccoli-dev Місяць тому

    Nice to see Russian shill Lex Fridman in the chat!

  • @morglod
    @morglod Місяць тому

    Bust Rust could also recover from panics lul jesus
    Blind people

  • @defeqel6537
    @defeqel6537 Місяць тому

    Perhaps it is time we invert the control flow and stop with this error handling madness

  • @meryplays8952
    @meryplays8952 Місяць тому

    Zig exceptions should be THE DEFINITION of exceptions. The rest are dangerous erroneous implementations of algebraic effects.

    • @idkravitz
      @idkravitz Місяць тому

      Thats identitcal to Result type in Rust and Either monad in Haskell, i guess Haskell did it first, cause if i recall correctly they were the first language to adopt monads and utilize them for imperative-like syntax sugar

    • @meryplays8952
      @meryplays8952 Місяць тому

      @@idkravitz Not identical to Rust result. Different semantics. I do not have experience with Haskell. Is it having the "other" exceptions too? Because Scala has "them".

    • @idkravitz
      @idkravitz Місяць тому

      @@meryplays8952 well for pure functions the only error types are Optional and Either (or whatever algebraic data type user can define with similar purpose, it's not enforced by language) and also unrecoverable panics (like when some very important assertion fails). In IO Monad there are try and catch functions that, well, does what you can expect them to do: try stops propagation by wrapping result in Either, catch applies recovering function if IO action results in IOError. Panics are rarely used in newer haskell libs, because user can't handle them. And only big brains know what transformer monads use for error handling.

  • @Naruto-oc6mi
    @Naruto-oc6mi 17 днів тому

    prime please come back to rust. i just found out that in very very hight traffic, rust beat the shit out of go, handling 2x bigger request per second than go lmao. also one of big company in my country just threw java out and switching to rust :

  • @rosehogenson1398
    @rosehogenson1398 Місяць тому

    always has

  • @MarekFajkus
    @MarekFajkus Місяць тому +1

    First language which introduced exceptions was Lisp. IT didn't have "Try" either. Try block was introduced in CLU. So to say go doesn't have exceptions seems like an attempt to rewrite history. I mean you can say go doesn't have compiler either. It's go geter the conqueror of worlds. It just happens to do exactly the same thing compilers do..

  • @s3rit661
    @s3rit661 Місяць тому +4

    Panic = throw
    Recover = try/catch

    • @KJImmy26
      @KJImmy26 Місяць тому +2

      struct + functions = class 😂

    • @s3rit661
      @s3rit661 Місяць тому +1

      @@KJImmy26 What about inehritance?

    • @KJImmy26
      @KJImmy26 Місяць тому

      @@s3rit661 composition over inheritance

    • @zirize
      @zirize Місяць тому

      This is very similar to VB's on error goto. While catch has a block to specify a specific section, go's recover or VB's on error cannot do that. Therefore, you need to strategically structure your functions.