Why Golang HTTP Handlers Should Return An Error

Sdílet
Vložit
  • čas přidán 12. 09. 2024
  • ► Join my Discord community for free education 👉 / discord
    ► Exclusive Lessons, Mentorship, And Videos 👉 / anthonygg_
    ► 33% OFF on my Go + HTMX + Templ Course PRESALE 👉bit.ly/3UFruxO
    ► Enjoy a 60% Black Friday Discount on My Golang Course 👉 fulltimegodev.com
    ► Learn how I became a self-taught software engineer 👉fulltimegodev....
    ► Follow me on Twitter 👉 / anthdm
    ► Follow me on GitHub 👉 github.com/anthdm
    Grab yourself a 33% OFF on the PRESALE event of my building production ready applications with GO + HTMX + Templ + Tailwindcss + JQuery course here: bit.ly/3UFruxO
    SUBSCRIBE OR NO MARGARITAS
    ╔═╦╗╔╦╗╔═╦═╦╦╦╦╗╔═╗
    ║╚╣║║║╚╣╚╣╔╣╔╣║╚╣═╣
    ╠╗║╚╝║║╠╗║╚╣║║║║║═╣
    ╚═╩══╩═╩═╩═╩╝╚╩═╩═╝

Komentáře • 53

  • @anthonygg_
    @anthonygg_  Před 5 měsíci +2

    ► 33% OFF on my Go + HTMX + Templ Course PRESALE 👉bit.ly/3UFruxO
    ► Join my Discord community for free education 👉 discord.com/invite/Ac7CWREe58
    ► Exclusive Lessons, Mentorship, And Videos 👉 www.patreon.com/anthonygg_
    ► 60% OFF on my Golang course 👉 fulltimegodev.com
    Thanks for watching

  • @eptic-c
    @eptic-c Před 5 měsíci +40

    The biggest problem on the internet is that everybody talks like they are experts but they never encountered real problems because they never needed real solutions.

    • @rafael.aloizio1769
      @rafael.aloizio1769 Před 5 měsíci

      You did a hell of a surgery here, congrats

    • @hjnp
      @hjnp Před 5 měsíci

      true la palisse!

  • @iliatalebzade8751
    @iliatalebzade8751 Před 5 měsíci +13

    It is the correct way when the handlers return an error, the example you showed was more than enough proof that it makes the code 100x better to have handlers return errors, but with standard libraries within each language there's a line of having all these utility and tools included in the best and most accessible shape while maintaining a certain level of keeping the tools "vanilla" so that each developer based on their specific needs can use them and utilize them, so with that I think not having handlers return an error is not a bad choice made by maintainers.
    Love your work, learned a ton from you, wish you the best 🔥🔥🔥

    • @anthonygg_
      @anthonygg_  Před 5 měsíci +4

      This makes sense. You have a point.

  • @henrythomas6356
    @henrythomas6356 Před 5 měsíci +8

    100% agree, almost everywhere you look in Golang where errors may occur they are returned.
    The HTTP handlers deviating from this feels wrong and results in hacky middleware solutions.

  • @mojixcoder
    @mojixcoder Před 5 měsíci +13

    Returning an error by HTTP handlers makes it really hard for other middlewares to find the correct and final response status code. Because global error handler gets called after all middlewares and handlers. I don’t agree with that.

    • @turkishcat4423
      @turkishcat4423 Před 5 měsíci +2

      I think you didn’t understand the example in the video…

    • @mojixcoder
      @mojixcoder Před 5 měsíci +1

      @@turkishcat4423I didn’t specifically talked about the video, I was talking about talking a concept in which you can handle errors after everything is finished in HTTP handlers.

    • @daderler4986
      @daderler4986 Před 5 měsíci +4

      @@mojixcoder The makeHandler() function writes the error in the response if the actual handler returns one. So middlewares will be able to read the response code and everything by looking at the response itself, like usual.

    • @jackielii
      @jackielii Před 5 měsíci

      I agree, IMHO the std http.Handler stays closest to the data flow model. You get the request, and the writer to write to the TCP stream. It gives maximum flexibility to what you need to achieve without having to thinking too much.
      I agree returning an error may make writing the handlers easier (70%? 90%?) in terms of LOC.
      A couple of month ago I wrote an nextjs chat app. I initially used the new App router which takes a request and returns an response. I had to switch to the old Pages router which passes in the response writer and request. Although one can achieve the same thing with both, but it's much easier to reason with the response writer passed in.

    • @mojixcoder
      @mojixcoder Před 5 měsíci

      @@daderler4986 in this example yes, but in other frameworks like echo it not designed like this and cant be designed like that. This is just a simple example and writing a wrapper around the stdlib. By doing so in a package like echo, all middlewares have to check returned errors as well as the response status code to predict the correct status code.

  • @rodjenihm
    @rodjenihm Před 5 měsíci +10

    Definitely makes handler cleaner.

  • @dhanielr
    @dhanielr Před 5 měsíci +10

    You are completely right. I work with Go about 4 years ago and before that i work with OOP languages. Don't get me wrong, i love to work with Go, but sometimes the community hugs to much the symplicity and when whe talk about scalability most of the times this is realy bad. This idea you put on the video is a simple application for adapter pattern and even that, the community repudiates. Very good video.

  • @arturfil
    @arturfil Před 5 měsíci +2

    Hey that's my comment! lol.
    I don't mind changing the way I code my project if I see a better way of doing so. I just don't personally see the need to return an error in the handler. I do return an error in the service itself or log the error in the handler, but I don't return it simply because I just setup the routes to the server struct and declare the controllers in the router setup.
    Also, I know that just because everyone does it in x way doesn't mean is right BUT they way I've seen handlers created, in books and articles and courses, is by not returning an error, but in the services instead because that's where an error could potentially come. If there is a potential error in the handler by setup, then I would just log it.
    Also, if you say there would be problems when logging errors, I do have helper functions that have a structured Error and returns that as JSON so that way if I need to change something I can reference to the struct and unfortunately yes, change all the writeError function instances.
    But again, I'm always open and happy to change the way I structure my code if I see a better way of doing so.

  • @paulbinkim6409
    @paulbinkim6409 Před 5 měsíci +2

    The reason why returning error is at one point becomes necessary is because handling error at your handler forces you to be context aware. Like Anthony showed in this video, you will have multiple different error types, then sentinel errors, network errors, where each needs to be handled different way. Imagine you having 100 handlers that does exhaustive error handling for 5~10 different cases and tell me error handling is doable...

  • @rolandinmarsat4309
    @rolandinmarsat4309 Před 5 měsíci +1

    Your approach makes more sense. I hadn't yet thought of implementing it the way you've shown. Although it is so obvious. This is an easier way to centralize error handling on an http server. Thank you!

  • @vyrwu
    @vyrwu Před 5 měsíci +8

    You can easily wrap handlers in funcs like you showed. Someone might have a different opinion and choose to handle each error separately. No need to add this behaviour to std lib if you can implement this in 5 mins by wrapping handlers. Don’t understand the discussion.

  • @P3PPING
    @P3PPING Před 5 měsíci +3

    The stdlib is written in such a way to make error handling your problem and not theirs. By not returning errors and forcing the developer to implement and handle them as they see fit is the correct implementation.
    Otherwise it becomes too opinionated and there are too many default cases the stdlib has to provide behaviour for.
    Stdlib only exists to provide the building blocks, its not there to tell you how to hang your curtains.
    I do like how you handle your errors though.

  • @arenhovsepyan1463
    @arenhovsepyan1463 Před 5 měsíci +3

    Anthony all these lessons are great, but share with your music playlist man!!

  • @acheraime
    @acheraime Před 5 měsíci +1

    That’s the reason why I love echo.

  • @vitiok78
    @vitiok78 Před 5 měsíci +4

    Anthony, please, don't be so angry when people tell you the truth about the errors and the lack of point to return them.
    Did you know why the Request variable in handle functions comes as a pointer and has the context inside? This is exactly the reason! You can add any values to that context and use them later in any middleware. So you can add errors in context and wrap the handler in WithErrorHandlingMiddleware. Here you will read that context from Request and use it how you want))) And the signature of your handler functions remains standard

    • @anthonygg_
      @anthonygg_  Před 5 měsíci +3

      Everyone is free to write and handle code as they please. Im just sharing my experience utilising this way of error handling. This is how Docker api does and how my 40 million dollar evaluated company does it. We are still friends.

    • @vitiok78
      @vitiok78 Před 5 měsíci

      @@anthonygg_
      Just try this. Look how clean handlers are
      package main
      import (
      "context"
      "fmt"
      "net/http"
      )
      func main() {
      server := http.NewServeMux()
      server.HandleFunc("/", withError(handle))
      fmt.Println("Serving...")
      http.ListenAndServe(":8080", server)
      }
      func withError(next http.HandlerFunc) http.HandlerFunc {
      return func(w http.ResponseWriter, r *http.Request) {
      next(w, r)
      if errors, ok := r.Context().Value("errors").([]error); ok {
      for _, err := range errors {
      fmt.Println(err)
      }
      }
      }
      }
      func handle(w http.ResponseWriter, r *http.Request) {
      fmt.Fprint(w, "Hello, World from handler!")
      err := fmt.Errorf("error from handler")
      handleError(r, err)
      }
      func handle2(w http.ResponseWriter, r *http.Request) {
      fmt.Fprint(w, "Hello, World from handler2!")
      err := fmt.Errorf("error from handler2")
      handleError(r, err)
      }
      func handleError(r *http.Request, err error) {
      if err == nil {
      return
      }
      errors := []error{err}
      if errs, ok := r.Context().Value("errors").([]error); ok {
      errors = append(errs, err)
      }
      ctx := context.WithValue(r.Context(), "errors", errors)
      req := r.WithContext(ctx)
      *r = *req
      }

    • @h3ckphy246
      @h3ckphy246 Před 2 měsíci

      Англоговорящие не используют скобочки как смайлики)))) Спалился

  • @carlosemiliovaldesvillegas9349
    @carlosemiliovaldesvillegas9349 Před 5 měsíci +1

    There always will be ego battles.
    I found a useful video. Thx!

  • @awesomedavid2012
    @awesomedavid2012 Před 5 měsíci

    Personally, now that I look at my prior code, the only thing I use the error return for is to do something like `return c.status...`. Essentially, so I can modify the context and then break control flow. Besides that, I haven't actually used the error return for explicit error handling.
    I suppose this may change if http itself returns an error but I would have to make an application with just http to determine if I actually care or not. I like the concept, but it may not be needed for me.

  • @matiasbpg
    @matiasbpg Před 5 měsíci

    I agree that it would have been better if http.Handler had return error and with a error handler at mux level. That being said a framework, IMO is an over kill for something so easy to accomplish. It is less ergonomic to have middlewere everywhere, so probably y would use a single middlewere on the mux ( because the mix is s http.Handler) and pass errors though context ( or a custom context to make sure error accessing is type safe)

  • @bartukocakara7794
    @bartukocakara7794 Před 5 měsíci +1

    Hey Anthony what do you think about job opporunities in europe and usa between java and go ? Which one is worth to learn ?

    • @marcs8325
      @marcs8325 Před 3 měsíci

      Java probably has more job opportunities, but it doesn't mean a Java job is "Java only". You might end up coding in Kotlin, or even build a Go microservice. But it will be listed as a Java job, because Java is absolutely required to maintain a large part of the code base.
      Same goes for .NET. I'm a .NET developer, but I do write Python sometimes and I'm looking at Go as well.
      It will be much harder to find a "Go only" job, because the language is relatively new.
      I also work on code which is 20 years old 😂 Large companies have lots of legacy code and they're not going to rewrite it just for fun.

  • @CaptainDouchie
    @CaptainDouchie Před 5 měsíci +1

    when is ur new go course coming out and how is it different from ur other go course?

  • @theme3763
    @theme3763 Před 5 měsíci +1

    i make a function which is writejsonerror and writejson the jsonerror write the error and log error while writejson is for the responses to write the json successful response and solved no need for return to be clean

  • @maciekwojdyna2271
    @maciekwojdyna2271 Před měsícem

    arjen robben is a real fucking engineer

  • @SergioHerreroCruz96
    @SergioHerreroCruz96 Před 5 měsíci +1

    Awesome, thank you!

  • @assaidy
    @assaidy Před měsícem

    That was very nice.

  • @MarinescuEdward
    @MarinescuEdward Před 5 měsíci

    Can you make video how to deploy golang apps wiht Github Actions

  • @dmitriykuvandikov5013
    @dmitriykuvandikov5013 Před 5 měsíci

    "Howto ruin primary argument of using gin/echo/whatever framework in 12 mins" from Antony :D

  • @user-zm2um4pg4w
    @user-zm2um4pg4w Před 4 měsíci

    RFS7807?

  • @pauloafpjunior
    @pauloafpjunior Před 5 měsíci

    Very good.

  • @user-kh5bk6ld5d
    @user-kh5bk6ld5d Před 5 měsíci

    Just use chi and chill (kidding, use echo or gin or gonet)

  • @cristophermoreno2290
    @cristophermoreno2290 Před 5 měsíci +1

    🔥🔥🔥 GIGACHAD

  • @mistart1633
    @mistart1633 Před 4 měsíci

    Thats a video for timmies

  • @NikolaPetkanski31337
    @NikolaPetkanski31337 Před 5 měsíci

    Having exceptions would render this approach useless.