1. 47
  1.  

  2. 17

    if err != nil { gets old even faster.

    I just started using Go recently and really find this to be annoying.

    1. 6

      I remember reading (on the Go blog maybe?) about doing a small “assert” function for things that can fail (like command line utilities), it’s been one of my favorites since then:

      func assert(err error) {
          if err != nil {
              log.Fatalf("Fatal error: %s\n", err.Error()) //or panic(err) if you want the debug info
          }
      }
      

      then you can just do something like:

      func readConfig(path string) (cfg Config) {
          file, err := os.Open(path)
          assert(err)
      
          err = json.NewDecoder(file).Decode(&cfg)
          assert(err)
      }
      

      Of course, if you’re doing web services or any sort of daemon you’d want to handle errors gracefully, without having them kill your app (unless you’re doing startup)

      1. 4

        I felt the same way for a while but eventually you get over it. There are other things that in other languages would take a lot to express but are short in Go (e.g., interface behavior).

        1. 4

          Personally I prefer this feture than exception, it’s more explicit than exception, and not that cubersome. Exceptions always make me worried that there may be some unhandled mess deep down the function call so I have to wrap the call with try catch block and finally it indents the main logic futher and gets ugly.

          EDIT: Besides, It’s extremely terrible to mix return error and throw exception in the same application, which is very common if you use different libraries with different error handling styles, while golang makes it consistent.

          1. 7

            Personally I prefer this feture than exception, it’s more explicit than exception, and not that cubersome.

            But it’s not a binary choice of nullable error types versus exceptions. Sum types solve this problem quite elegantly, especially combined with some facilities to ‘unwrap’ instances of such types safely (e.g. try! in Rust or the Maybe/Either monads in Haskell).

          2. 5

            A lot of Go’s features are slick, but this error handling is indeed pretty ugly. I wonder what the underlying reasons were for them to implement it like this.

            1. 19

              Explicit over magic.

              1. 5

                This, so much this.

                It’s ugly, but it’s clean enough that I miss it when working with other languages. I always find myself having to deal with C++ functions that might throw exceptions, PHP functions that either use exceptions or have their own get_last_error() function. Haskell which has just about a bajillion ways to do errors (and this 15 pages guide only covers some of them).

                Go’s error handling is one of those things that make it boring as hell, but also what makes it so easy to be productive at. I just never overthink stuff as much as I do with other languages.

                1. 4

                  What about error handling in Rust? It’s basically unwrap() if you want to ignore the error or propagating it (via try!). Other things like ignore and use default value X are also possible.

                  The main benefit over Go is that you have to handle the error somehow. You can’t forget to ignore it, and you have to ignore it explicitly if you want to.

                  1. 2

                    Haven’t had to deal with Rust yet, so I really don’t know what you’re talking about, sorry!

                    Maybe I should try it again at some point (never seriously considered in the past due to the constantly changing API).

                    1. 3

                      The API has been stable for over a year now, so if you’re interested, now would be a good time to try it out!

                    2. 1

                      Don’t forget that Rust still has panics, which for me show up most commonly on array and Vec indexing when I’ve got a bug. Granted, this kind of exception almost always shows up in testing for me, and I rarely encounter libraries which panic on their own, but it’s worth remembering that Result<T, E> isn’t the only way that Rust handles error conditions. I personally don’t worry nearly as much about panics as I do unchecked exceptions in Java or Python, but nonetheless it’s worth noting that Rust doesn’t offer a panacea here, just different tradeoffs (which I’m quite happy with).

                      1. 1

                        Go also has panics though, so it’s not really a differentiator.

                        1. 1

                          I wasn’t attempting to differentiate Rust vs. Go though. If I wanted to differentiate Rust and Go re: error handling, I would point out that the Rust Result<T, E> type issues compiler warnings if you neglect to use it, whereas Go doesn’t appear to do that (although I haven’t written more than hello world in Go). I was pointing out that Result isn’t the whole error handling story in Rust.

                  2. 1

                    arguably the key aspect of djb’s coding style that leads to fewer bugs in practice is extremely explicit error handling. I’m sure the OpenBSD folks handle errors the same way.

                    1. -3

                      Laziness, more like.

                      1. 6

                        I’d believe that for most other teams. But Go is really a language that has been designed. Even OCaml, a language I like very much, with tons of very fancy features, feels less cohesive and cleanly designed than Go.

                        1. 2

                          That’s well possible since MLs like OCaml consist of the core language and the module language and these feel a bit different. There is 1ML which tries to unify these in a coherent whole. Plus OCaml has a lot of syntax and type system featured plastered over the the underlying ML type system which make it a more flexible language but also a more complex.

                          Maybe it’s also because languages which can be completely understandstood feel more “designed” because it is easier to grasp the design and see how things fit together?

                          1. 2

                            More intellectual laziness. “Return values worked for me, why should I do anything else?” Thompson et al are certainly smart and accomplished, but definitely fossilized in their thinking.

                    2. 1

                      Learning the Maybe monad in Haskell started my love affair with the language. After my mixed experience with Go it was particularly prescient.

                      1. 1

                        I will take the balance of good enough features plus fast builds over richer features and painful builds every time. This is definitely an area where personal preference is the deciding factor.

                    3. 9

                      Yes, the whole, let’s use GO for everything is pretty crazy. Python/Ruby are fast enough for the vast majority tasks, especially for web where your programming language is mainly glue between databases and a browser.

                      1. 14

                        I challenge you to reverse the languages in your statement and reread … with some squinting. It’s almost exactly the situation we were in in the late 90s when scripting languages were becoming fast enough to replace “real” languages like C++.

                        One other point to this–web apps are increasingly being replaced by rich JavaScript apps and web APIs. I’d love to say that writing web APIs in go is great, but it is definitely not.

                        The truth is, though, the go stdlib (and community packages) has enough convenience in it to challenge scripting languages in development speed if you know what you are doing with it. And, for that you get some static checks, free CPU cycles, more free memory, etc. You might copy and paste more because the means to abstract are limited, and you might do a fair number of if err == nil checks, but it’s doable.

                        But go is also a pretty terrible language to spend your day in, in my opinion as a full time gopher, if you’ve been exposed to any other language containing features that were developed after 1979.

                        1. 1

                          But go is also a pretty terrible language to spend your day in, in my opinion as a full time gopher, if you’ve been exposed to any other language containing features that were developed after 1979.

                          Hi! I’m your counter example. I spend my days in Go and find it very enjoyable, yet I spend my nights in languages containing “features that were developed after 1979.” (Sometimes my nights are spent in Go, too, considering I wrote most of my window management software in Go.)

                          1. 1

                            I spend my days in Go and find it very enjoyable

                            I’m very happy for you. I do write Go in my spare time as well, not because I enjoy it–because it’s a practical language to get real work done in, ships easily, etc. It’s a tool. It doesn’t fit my hand as comfortable as other tools, but it gets the job done.

                            (I’m glad you changed your mind about your original parenthesized comment.)

                      2. 4

                        Error handling, interface {}s, package management, no comprehensions, slice behaviour … lots of things that fall on the “annoying” spectrum. But I’ve used Go in a few successful projects and it has a list of attractive features too, including fast adoption and a solid stdlib. Compile times and static builds are also pretty great.

                        I’ve been on the hunt for the sweet spot building web and back end services and have yet to find a language that fully satisfies.

                        1. 2

                          What was the reason to switch to Python to Go, I don’t think I read that in this particular article?

                          1. 2

                            Batteries included: argparse, pty, locale, configparser, json, uuid, http. All of these excellent modules are used by asciinema and are part of Python’s standard library. Python stdlib’s quality and stability guarantees are order of magnitude higher than of unversioned Go libs from Github

                            That sounds odd to me – These are also parts of Go’s stdlib, and aren’t unversioned go libs from github. And, honestly, I trust Go’s stability guarantees quite a bit more than Python’s.

                            1. 1

                              Even if Go were perfect on a technical level, the online community is really stiff compared to Elixir, JavaScript, Ruby, and Rust. That’s reason enough to stay away.