1. 34

    return err is almost always the wrong thing to do. Instead of:

    if err := foo(); err != nil {
    	return err
    }
    

    Write:

    if err := foo(); err != nil {
    	return fmt.Errorf("fooing: %w", err)
    }
    

    Yes, this is even more verbose, but doing this is what makes error messages actually useful. Deciding what to put in the error message requires meaningful thought and cannot be adequately automated. Furthermore, stack traces are not adequate context for user-facing, non-programming errors. They are verbose, leak implementation details, are disrupted by any form of indirection or concurrency, etc.

    Even with proper context, lots of error paths like this is potentially a code smell. It means you probably have broader error strategy problems. I’d try to give some advice on how to improve the code the author provided, but it is too abstract in order to provide any useful insights.

    1. 18

      I disagree on a higher level. What we really want is a stacktrace so we know where the error originated, not manually dispensed breadcrumbs…

      1. 32

        maybe you do, but I prefer an error chain that was designed. A Go program rarely has just one stack, because every goroutine is its own stack. Having the trace of just that one stack isn’t really a statement of the program as a whole since there’s many stacks, not one. Additionally, stack traces omit the parameters to the functions at each frame, which means that understanding the error means starting with your stack trace, and then bouncing all over your code and reading the code and running it in your head in order to understand your stack trace. This is even more annoying if you’re looking at an error several days later in a heterogeneous environment where you may need the additional complication of having to figure out which version of the code was running when that trace originated. Or you could just have an error like “failed to create a room: unable to reserve room in database ‘database-name’: request timed out” or something similar. Additionally, hand-crafted error chains have the effect that they are often much easier to understand for people who operate but don’t author something; they may have never seen the code before, so understanding what a stack trace means exactly may be difficult for them, especially if they’re not familiar with the language.

        1. 6

          I dunno. Erlang and related languages give you back a stack trace (with parameters) in concurrently running processes no problem

          1. 5

            It’s been ages since I wrote Erlang, but I remember that back then I rarely wanted a stack trace. My stack were typically 1-2 levels deep: each process had a single function that dispatched messages and did a small amount of work in each one. The thing that I wanted was the state of the process that had sent the unexpected message. I ended up with some debugging modes that attached the PID of the sending process and some other information so that I could reconstruct the state at the point where the problem occurred. This is almost the same situation as Go, where you don’t want the stack trace of the goroutine, you want to capture a stack trace of the program at the point where a goroutine was created and inspect that at the point where the goroutine failed.

            This isn’t specific to concurrent programs, though it is more common there, it’s similar for anything written in a dataflow / pipeline style. For example, when I’m debugging something in clang’s IR generation I often wish I could go back and see what had caused that particular AST node to be constructed during parsing or semantic analysis. I can’t because all of the state associated with that stack is long gone.

        2. 10

          FWIW, I wrote a helper that adds tracing information.

          I sort of have two minds about this. On the one hand, yeah, computers are good at tracking stack traces, why are we adding them manually and sporadically? OTOH, it’s nice that you can decide if you want the traces or not and it gives you the ability to do higher level things like using errors as response codes and whatnot.

          The thing that I have read about in Zig that I wish Go had is an error trace which is different from the stack trace, which shows how the error was created, not the how the error propagates back to the execution error boundary which is not very interesting in most scenarios.

          1. 7

            The nice thing about those error traces is that they end where the stack trace begins, so it’s seamless to the point that you don’t even need to know that they are a thing, you just get exactly the information that otherwise you would be manually looking for.

          2. 8

            In a multiprocess system that’s exchanging messages: which stack?

            1. 2

              see: erlang

            2. 5

              You don’t want stack traces; you want to know what went wrong.

              A stack trace can suggest what may have gone wrong, but an error message that declares exactly what went wrong is far more valuable, no?

              1. 8

                An error message is easy, we already have that: “i/o timeout”. A stack trace tells me the exact code path that lead to that error. Building up a string of breadcrumbs that led to that timeout is just a poorly implemented, ad-hoc stack trace.

                1. 5

                  Indeed and I wouldn’t argue with that. I love a good stack trace, but I find they’re often relied upon in lieu of useful error messages and I think that’s a problem.

                  1. 2

                    Building up a string of breadcrumbs that led to that timeout is just a poorly implemented, ad-hoc stack trace.

                    That’s a bit of an over-generalization. A stack trace is inherently a story about the construction of the program that originated the error, while an error chain is a story about the events that led to an error. A stack trace can’t tell you what went wrong if you don’t have access to the program’s source code in the way that a hand crafted error chain can. A stack trace is more about where an error occurred, while an error chain is more about why an error occurred. I think they’re much more distinct than you are suggesting.

                    and of course, if people are just bubbling up errors without wrapping them, yeah you’re going to have a bad time, but I think attacking that case is like suggesting that every language that has exceptions encourages Pokémon exception handling. That’s a bad exception-handling pattern, but I don’t think that the possibility of this pattern is a fair indictment of exceptions generally. Meanwhile you’re using examples of bad error handling practices that are not usually employed by Go programmers with more than a few weeks experience to indict the entire paradigm.

                2. 4

                  Stack traces are expensive to compute and inappropriate to display to most users. Also, errors aren’t exceptions.

                  1. 1

                    That’s why Swift throws errors instead. Exceptions immediately abort the program.

                  2. 3

                    What really is the “origin” of an error? Isn’t that somewhat arbitrary? If the error comes from a system call, isn’t the origin deeper in the kernel somewhere? What if you call in to a remote, 3rd party service. Do you want the client to get the stack trace with references to the service’s private code? If you’re using an interface, presumably the purpose is to abstract over the specific implementation. Maybe the stack trace should be truncated at the boundary like a kernel call or API call?

                    Stack traces are inherently an encapsulation violation. They can be useful for debugging your internals, but they are an anti-feature for your users debugging their own system. If your user sees a stack trace, that means your program is bugged, not theirs.

                    1. 5

                      I get a line of logging output: error: i/o timeout. What do I do with that? With Ruby, I get a stack trace which tells me exactly where the timeout came from, giving me a huge lead on debugging the issue.

                      1. 5

                        I get a line of logging output: error: i/o timeout. What do I do with that?

                        Well, that’s a problem you fix by annotating your errors properly. You don’t need stack traces.

                        1. 3

                          When your Ruby service returns an HTTP 500, do you send me the stack trace in the response body? What do I do with that?

                          Go will produce stack traces on panics as well, but that’s precisely the point here: these are two different things. Panics capture stack traces as a “better than nothing” breadcrumb trail for when the programmer has failed to account for a possibility. They are for producers of code, not consumers of it.

                        2. 2

                          There’s definitely competing needs between different audiences and environments here.

                          A non-technical end user doesn’t want to see anything past “something went wrong on our end, but we’re aware of it”. Well, they don’t even want to see that.

                          A developer wants to see the entire stack trace, or at least have it available. They probably only care about frames in their own code at first, and maybe will want to delve into library code if the error truly doesn’t seem to come from their code or is hard to understand in the first place.

                          A technical end user might want to see something in-between: they don’t want to see “something was wrong”. They might not even want to see solely the outer error of “something went wrong while persisting data” if the root cause was “I couldn’t reach this host”, because the latter is something they could actually debug within their environment.

                      2. 9

                        This is one reason I haven’t gone back to Go since university - There’s no right way to do anything. I think I’ve seen a thousand different right ways to return errors.

                        1. 9

                          Lots of pundits say lots of stuff. One good way to learn good patterns (I won’t call them “right”), is to look at real code by experienced Go developers. For instance, if you look at https://github.com/tailscale/tailscale you’ll find pervasive use of fmt.Errorf. One thing you might not see – at least not without careful study – is how to handle code with lots of error paths. That is by it’s very nature harder to see because you have to read and understand what the code is trying to do and what has to happen when something goes wrong in that specific situation.

                          1. 6

                            there is a right way to do most things; but it takes some context and understanding for why.

                            the mistake is thinking go is approachable for beginners; it’s not.

                            go is an ergonomic joy for people that spend a lot of time investing in it, or bring a ton of context from other languages.

                            for beginners with little context, it is definitely a mess.

                            1. 9

                              I thought Go was for beginners, because Rob Pike doesn’t trust programmers to be good.

                              1. 18

                                I’d assume that Rob Pike, an industry veteran, probably has excellent insight into precisely how good the average programmer at Google is, and what kind of language will enable them to be productive at the stuff Google makes. If this makes programming languages connaisseurs sad, that’s not his problem.

                                1. 9

                                  Here’s the actual quote:

                                  The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.

                                  So I have to wonder who is capable of understanding a “brilliant language” …

                                  1. 8

                                    So I have to wonder who is capable of understanding a “brilliant language” …

                                    Many people. They don’t work at Google at an entry-level capacity, that’s all.

                                    There’s a subtle fallacy at work here - Google makes a lot of money, so Google can afford to employ smart people (like Rob Pike!) It does not follow that everyone who works at Google is, on average, smarter than anyone else.

                                    (edited to include quote)

                                    1. 8

                                      Let’s say concretely we are talking about OCaml. Surely entry-level Googlers are capable of understanding OCaml. Jane Street teaches it to all new hires (devs or not) in a two-week bootcamp. I’ve heard stories of people quickly becoming productive in Elm too.

                                      The real meaning of that quote is not ‘entry-level Googlers are not capable of it’, it’s ‘We don’t trust them with it’ and ‘We’re not willing to invest in training them in it’. They want people to start banging out code almost instantly, not take some time to ramp up.

                                      1. 8

                                        Let’s say concretely we are talking about OCaml. Surely entry-level Googlers are capable of understanding OCaml. Jane Street teaches it to all new hires (devs or not) in a two-week bootcamp.

                                        I suspect that Jane Street’s hiring selects for people who are capable of understanding OCaml; I guarantee that the inverse happens and applicants interested in OCaml self select for careers at Jane Street, just like Erlang-ers used to flock towards Ericsson.

                                        Google has two orders of magnitude more employees than Jane Street. It needs a much bigger funnel and is likely far less selective in hiring. Go is “the law of large numbers” manifest as a programming language. That’s not necessarily bad, just something that is important for a massive software company and far less important for small boutiques.

                                        1. 2

                                          applicants interested in OCaml self select for careers at Jane Street,

                                          As I said, they teach it to all hires, including non-devs.

                                          Google has two orders of magnitude more employees than Jane Street. It needs a much bigger funnel and is likely far less selective in hiring

                                          Surely though, they are not so loose that they hire Tom Dick and Harry off the street. Why don’t we actually look at an actual listing and check? E.g. https://careers.google.com/jobs/results/115367821606560454-software-developer-intern-bachelors-summer-2022/

                                          Job title: Software Developer Intern, Bachelors, Summer 2022 (not exactly senior level)

                                          Minimum qualifications:

                                          Pursuing a Bachelor’s degree program or post secondary or training experience with a focus on subjects in software development or other technical related field. Experience in Software Development and coding in a general purpose programming language. Experience coding in two of C, C++, Java, JavaScript, Python or similar.

                                          I’m sorry but there’s no way I’m believing that these candidates would be capable of learning Go but not OCaml (e.g.). It’s not about their capability, it’s about what Google wants to invest in them. Another reply even openly admits this! https://lobste.rs/s/yjvmlh/go_ing_insane_part_one_endless_error#c_s3peh9

                                          1. 2

                                            And I remember when Google would require at minimum a Masters Degree before hiring.

                                            1. 1

                                              I had a master’s degree in engineering (though not in CS) and I couldn’t code my way out of a paper bag when I graduated. Thankfully no-one cared in Dot Com Bubble 1.0!

                                          2. 3

                                            They want people to start banging out code almost instantly, not take some time to ramp up.

                                            Yes, and? The commodification of software developers is a well-known trend (and goal) of most companies. When your assets are basically servers, intangible assets like software and patents, and the people required to keep the stuff running, you naturally try to lower the costs of hiring and paying salary, just like you try to have faster servers and more efficient code.

                                            People are mad at Rob Pike, but he just made a language for Google. It’s not his fault the rest of the industry thought “OMG this is the bee’s knees, let’s GO!” and adopted it widely.

                                            1. 1

                                              Yes, I agree that the commodification of software developers is prevalent today. And we can all see the result, the profession is in dire straits–hard to hire because of bonkers interview practices, hard to keep people because management refuses to compensate them properly, and cranking out bugs like no tomorrow.

                                            2. 2

                                              on the contrary, google provides a ton of ramp up time for new hires because getting to grips with all the internal infrastructure takes a while (the language is the least part of it). indeed, when I joined a standard part of the orientation lecture was that whatever our experience level was, we should not expect to be productive any time soon.

                                              what go (which I do not use very much) might be optimising for is a certain straightforwardness and uniformity in the code base, so that engineers can move between projects without having to learn essentially a new DSL every time they do.

                                              1. 1

                                                You may have a misconception that good programming languages force people to ‘essentially learn a new DSL’ in every project. In any case, as you yourself said, the language is the least part of the ramp-up of a new project, so even if that bit were true, it’s still optimizing for the wrong thing.

                                                1. 1

                                                  no, you misunderstood what i was getting at. i was saying that go was optimisng for straightforwardness and uniformity so that there would be less chance of complex projects evolving their own way of doing things, not that better languages would force people to invent their own DSLs per project.

                                                  also the ramp-up time i was referring to was for new hires; a lot of google’s internal libraries and services are pretty consistently used across projects (and even languages via bindings and RPC) so changing teams requires a lot less ramp up than joining google in the first place.

                                                  1. 1

                                                    i was saying that go was optimisng for straightforwardness and uniformity so that there would be less chance of complex projects evolving their own way of doing things,

                                                    Again, the chances of that happening are not really as great as the Go people seem to be afraid it is, provided we are talking about a reasonable, good language. So let’s say we leave out Haskell or Clojure. The fear of language-enabled complexity seems pretty overblown to me. Especially considering the effort put into the response, creating an entirely new language and surrounding ecosystem.

                                      2. 9

                                        No, Rob observed, correctly, that in an organization of 10,000 programmers, the skill level trends towards the mean. And so if you’re designing a language for this environment, you have to keep that in mind.

                                        1. 4

                                          it’s not just that. It’s a language that has to reconcile the reality that skill level trends toward the mean, with the fact that the way that google interviews incurs a selection/survival bias towards very junior programmers who think they are the shit, and thus are very dangerous with the wrong type of power.

                                          1. 4

                                            As I get older and become, presumably, a better programmer, it really does occur to me just how bad I was for how long. I think because I learned how to program as a second grader, I didn’t get how much of a factor “it’s neat he can do it all” was in my self-assessment. I was pretty bad, but since I was being compared to the other kids who did zero programming, it didn’t matter that objectively I was quite awful, and I thought I was hot shit.

                                          2. 4

                                            Right! But the cargo-cult mentality of the industry meant that a language designed to facilitate the commodification of software development for a huge, singular organization escaped and was inflicted on the rest of us.

                                            1. 4

                                              But let’s be real for a moment:

                                              a language designed to facilitate the commodification of software development

                                              This is what matters.

                                              It doesn’t matter if you work for a company of 12 or 120,000: if you are paid to program – that is, you are not a founder – the people who sign your paychecks are absolutely doing everything within their power to make you and your coworkers just cogs in the machine.

                                              So I don’t think this is a case of “the little fish copying what big bad Google does” as much as it is an essential quality of being a software developer.

                                              1. 1

                                                Thank you, yes. But also, the cargo cult mentality is real.

                                          3. 2

                                            Go is for compilers, because Google builds a billion lines a day.

                                      3. 2

                                        return errors.Wrapf(err, "fooing %s", bar) is a bit nicer.

                                        1. 13

                                          That uses the non-standard errors package and has been obsolete since 1.13: https://stackoverflow.com/questions/61933650/whats-the-difference-between-errors-wrapf-errors-errorf-and-fmt-errorf

                                          1. 1

                                            Thanks, that’s good to know.

                                          2. 8

                                            return fmt.Errorf("fooing %s %w", bar, err) is idiomatic.

                                            1. 8

                                              Very small tweak: normally you’d include a colon between the current message and the %w, to separate error messages in the chain, like so:

                                              return fmt.Errorf("fooing %s: %w", bar, err)
                                              
                                          3. 1

                                            It makes error messages useful but if it returns a modified err then I can’t catch it further up with if err == someErr, correct?

                                            1. 2

                                              You can use errors.Is to check wrapped errors - https://pkg.go.dev/errors#Is

                                              Is unwraps its first argument sequentially looking for an error that matches the second. It reports whether it finds a match. It should be used in preference to simple equality checks

                                              1. 2

                                                Thanks! I actually didn’t know about that.

                                              2. 2

                                                Yes, but you can use errors.Is and errors.As to solve that problem. These use errors.Unwrap under the hood. This error chaining mechanism was introduced in Go 1.13 after being incubated in the “errors” package for a long while before that. See https://go.dev/blog/go1.13-errors for details.

                                            1. 1

                                              Doesn’t actually explain what A/UX is. 🤷🏻‍♂️ I guess we are suppose to know.

                                              1. 3

                                                So many things here reuse old names of old projects and I always feel like im at fault for knowing Scala is some pre PowerPoint app for the Amiga.

                                                Anyway I guess I should write something about the OS X of the 1980s, when System 6 and 7 were decapitated and put on top of Unix System Vr2.

                                                  1. 2

                                                    Purely by the name I assumed it was an old Unix machine or OS (I have vaguely heard of HP-UX and it sort of sounds like that). I guess I spend way too much time here or something.

                                                    1. 1

                                                      https://virtuallyfun.com/wordpress/2021/09/19/so-what-is-the-deal-with-a-ux-anyways/

                                                      I added some stuff about ‘big mac’ the next departure, the lawsuits and didn’t want to make it all next but a few version tours of A/UX, and thoughts on the identity crissis.

                                                    1. 13

                                                      I distribute my Go-based commercial software in an alpine-based Docker container which weighs in at 15MB. 5MB is my software, 3-4MB is ca-certificates. Alpine and musl are tiny and wonderful.

                                                      1. 10

                                                        Good to know I could still fit my livelihood on a few 1.44MB floppies. 🤣

                                                        1. 5

                                                          . Single JAR file is a statically linked package for Java apps for example. You can do the same thing with AWS Lambda packages (single zip).

                                                          Are you using some custom ca? AFAIK, those certs are still around <1MB.

                                                          du -sh /usr/share/ca-certificates/

                                                          616.0K /usr/share/ca-certificates/

                                                          1. 4

                                                            Why not use a scratch container? What does all that overhead get you?

                                                          1. 24

                                                            Upgrading @golang versions is actually a pleasurable task for me:

                                                            1. I’m 99% sure nothing will break.
                                                            2. Speedups of 5-10% are common.
                                                            3. New compiler or vet warnings tell me how to improve my code.
                                                            4. Excellent release notes.

                                                            Does any other language get this as right?

                                                            1. 6

                                                              Go’s secret sauce is that they never† break BC. There’s nothing else where you can just throw it into production like that because you don’t need to check for deprecations and warnings first.

                                                              † That said, 1.17 actually did break BC for security reasons. If you were interpreting URL query parameters so that ?a=1&b=2 and ?a=1;b=2 are the same, that’s broken now because they removed support for semicolons for security reasons. Seems like the right call, but definitely one of the few times where you could get bitten by Go.

                                                              Another issue is that the language and standard library has a compatibility guarantee, but the build tool does not, so e.g. if you didn’t move to modules, that can bite you. Still, compared to Python and Node, it’s a breath of fresh air.

                                                              1. 2

                                                                I’ve been upgrading since 1.8 or so. There have been (rarely) upgrades that broke my code, but it was always for a good reason and easy to fix. None in recent memory.

                                                                1. 1

                                                                  1.16 or 1.15 also broke backwards compatibility with the TLS ServerName thing.

                                                                2. 4

                                                                  Java is damn good about backward compatibility.

                                                                  From what I recall, their release notes are pretty good as well.

                                                                  1. 2

                                                                    As someone with just a little experience with Go, what’s the situation with dependencies? In Java and maven, it becomes a nightmare with exclusions when one wants to upgrade a dependency, as transitive dependencies might then clash.

                                                                    1. 3

                                                                      It’s a bit complicated, but the TL;DR is that Go 1.11 (this is 1.17, recall) introduced “modules” which is the blessed package management system. It’s based on URLs (although weirdly, it’s github.com, not com.github, hmm…) that tell the system where to download external modules. The modules are versioned by git tags (or equivalent for non-git SCMs). Your package can list the minimum versions of external packages it wants and also hardcode replacement versions if you need to fork something. The expectation is that if you need to break BC as a library author, you will publish your package with a new URL, typically by adding v2 or whatever to the end of your existing URL. Package users can import both github.com/user/pkg/v1 and github.com/user/pkg/v2 into the same program and it will run both, but if you want e.g. both v1 and v1.5 in the same application, you’re SOL. It’s extremely opinionated in that regard, but I haven’t run into any problems with it.

                                                                      Part of the backstory is that before Go modules, you were just expected to never break BC as a library author because there was no way to signal it downstream. When they switched to modules, Russ Cox basically tried to preserve that property by requiring URL changes for new versions.

                                                                      1. 2

                                                                        The module name and package ImportPath are not required to be URLs. Them being a URL is overloading done by go get. Nothing in the language spec requires them to be URLs.

                                                                        1. 1

                                                                          Yes, but I said “TL;DR” so I had to simplify.

                                                                      2. 2

                                                                        I also have only a little experience with Go. I have not yet run into frustrations with dependencies via Go modules.

                                                                        Russ Cox gave a number of great articles talking about how Go’s dependency management solves problems with transitive dependencies. I recall this one being very good (https://research.swtch.com/vgo-import). It also calls out a constraint that programmers must follow:

                                                                        In Go, if an old package and a new package have the same import path, the new package must be backwards compatible with the old package.

                                                                        Is this constraint realistic and followed by library authors? If not, you’re going to run into problems with Go modules.

                                                                        I’ve run into dependency hell in: Java, JavaScript, Python, and PHP – In every programming language I’ve had to do major development in. It’s a hard problem to solve!

                                                                          1. 1

                                                                            Is this constraint realistic and followed by library authors? If not, you’re going to run into problems with Go modules.

                                                                            It is (obviously) not realistic for most software produced in the world.

                                                                        1. 2

                                                                          I had a different experience, going from Java 8 to Java 11 broke countless libraries for me. Especially bad is that they often break at run- and not at compile time.

                                                                          1. 1

                                                                            I strongly agree. The first time major stuff broke was Java 9, which is exceedingly recent, and wasn’t an LTS. And that movement has more in common with the Go 2 work than anything else, especially as Java 8 continues to be fully supported.

                                                                        1. 14

                                                                          Good grief, Junio sounds like Ulrich Drepper.

                                                                          1. 7

                                                                            I see kemitchell, I upvote. Is there anyone else hacking on OSS licensing? Your efforts are appreciated, Kyle.

                                                                            Like others, I’m defaulting to xGPL these days.

                                                                            1. 7

                                                                              I use appreciate their work, and the Blue Oak Model is a gem especially, as are much of their blogging, but very little is the licenses here are OSS, rather most are explicit attempts at business proprietary licensing, but in a generic way borrowed from OSS.

                                                                              1. 4

                                                                                Most of the lawyers here are also up to good hijinks: https://writing.kemitchell.com/lists/Blogroll.html

                                                                                None of the stuff mentioned in the blog post is my work alone!

                                                                                1. 2

                                                                                  I wouldn’t count this as “hacking on” but I’ve become a fan of the UPL since I found out about it: https://lobste.rs/s/u0illx/universal_permissive_license

                                                                                  1. -1

                                                                                    I’m defaulting to CDDL these days just to keep xGPLers out of my projects. (Also, MIT-0 for those projects which I want to be wide-spread.)

                                                                                    1. 4

                                                                                      That… sounds very stupid? Why would you purposefully prohibit yourself from using any GPL code? You choose to be unable to dynamically link against GPL libraries, and to be unable to statically link against LGPL libraries, and for what? To make some imagined other people a bit less happy?

                                                                                      1. 1

                                                                                        Honestly, I have not missed any GPL library in the past few years. I think that this is a hypothetical problem, after all.

                                                                                        Leaving this aside, I find the CDDL rather fitting for most of my projects which is a better reason, I guess.

                                                                                  1. 1

                                                                                    Links without any surrounding context aren’t very useful. Why?

                                                                                    1. 2

                                                                                      I was cheering until unsafe was used. Come on, don’t play stupid games to avoid one allocation.

                                                                                      1. 1

                                                                                        Yeah, this was the one part of the post I didn’t agree with.

                                                                                        I was also curious there was no mention of strings.Builder.

                                                                                      1. 6

                                                                                        I wish this included some explanation of why these are useful or explanations of why they are. Like, why use zerolog over logrus/zap/whatever? Why use gorilla/mux over gin or go-chi or the standard library? Why have that overly-complex unique code thing to determine where a logged error is thrown instead of making sure your errors have stack traces?

                                                                                        1. 4

                                                                                          I’m not the author of the post, but I can try to answer some questions:

                                                                                          Like, why use zerolog over logrus/zap/whatever?

                                                                                          zerolog and zap is what the author of logrus admit he would write if he wrote logrus/v2. zerolog claims to be a “better” version of zap (there are claims of performance improvement on other people’s computers)

                                                                                          Why use gorilla/mux over gin or go-chi or the standard library?

                                                                                          gorilla/mux is much lightweight as opposed to gin which has renderers, etc… Also, there are claims of very high performance on other people’s computers. With gorlla/mux you can plug your own json de-/serialization library which is faster than gin’s.

                                                                                          Why have that overly-complex unique code thing to determine where a logged error is thrown instead of making sure your errors have stack traces?

                                                                                          ¯\(ツ)/¯ No idea… The unique code approach feels very hacky and brittle to me.

                                                                                          1. 3

                                                                                            I would even suggest “httprouter” as a more lightweight alternative to gorilla/mux.

                                                                                            1. 2

                                                                                              Most “higher level” Go routers are probably based on it anyways.

                                                                                            2. 1

                                                                                              We use unique logging codes for our logs, and it makes it easier to locate a particular statement in either the logs, or the source code. Now, we generate the unique code by hand, but it’s not a horrendous issue for us (we have a separate document that records each logging statement).

                                                                                            3. 1

                                                                                              I’d be curious to know the best practices for annotating errors with stack traces. Any good library suggestions?

                                                                                              1. 3

                                                                                                github.com/pkg/errors has some nice helpers, as described in its documentation. The issue is that it requires changing your code to using errors.Errorf() instead of fmt.Errorf().

                                                                                                Go2 will do it differently, but natively

                                                                                                1. 3

                                                                                                  Also, errors.Wrapf is very useful when handling errors from packages which don’t use errors.

                                                                                                  1. 2

                                                                                                    You can wrap errors using fmt.Errorf() and the %w verb, and then later deal with them using errors.Is() or errors.As() and friends.

                                                                                                    1. 1

                                                                                                      That doesn’t give you stack traces though, correct?

                                                                                                  2. 2

                                                                                                    YES. This is probably my biggest issue with supporting production Go code. Errors are still too hard to locate.

                                                                                                    1. 1

                                                                                                      I personally use this to manage all that. If you use the errors.Wrap() function to wrap errors, it’ll add stack traces. And if you want to make a new error, the errors.New() function will also add a stack track where it was called. Then when you’re logging the error make sure it’s being logged in a way that will not just print the message. Most loggers should have a way to do that (I know zerolog and logrus do).

                                                                                                      1. 1

                                                                                                        Shameless plug for my errors library: https://pkg.go.dev/github.com/zeebo/errs/v2

                                                                                                        • captures stack traces, but only once even if wrapped multiple times
                                                                                                        • plays nicely with standard library errors package with errors.Is and errors.As
                                                                                                        • has a “tag” feature to let you associate and query tags with errors
                                                                                                        • helper to keep track of groups of errors
                                                                                                    1. 9

                                                                                                      When was the last time a major programming language removed a major feature? Nice to see they have a long term plan for the deprecation process.

                                                                                                      1. 3

                                                                                                        Agreed, too few programming languages have mature policies around this.

                                                                                                        (Rust is probably a good example of a new-ish language going down the non-sustainable route of “we are not going to remove anything ever”.)

                                                                                                        1. 1

                                                                                                          Isn’t the purpose of Rust Editions to allow making backwards incompatible changes like removing/fixing functions and features?

                                                                                                          1. 1

                                                                                                            No:

                                                                                                            Editions can contain incompatible changes, such as including a new keyword that conflicts with identifiers in code. However, unless you opt in to those changes, your code will continue to compile even as you upgrade the Rust compiler version you use.

                                                                                                            All Rust compiler versions support any edition that existed prior to that compiler’s release, and they can link crates of any supported editions together. Edition changes only affect the way the compiler initially parses code.

                                                                                                          2. 1

                                                                                                            Java itself still ships APIs that were deprecated 20 years ago, mainly because there’s no replacement for it. Thread.kill might be unsafe but there’s no alternative.

                                                                                                            As a long time Rubyist, there’s a number of features which do not provide the enough bang for the buck and I’d like to see removed. Matz has been willing to remove unpopular features, eg $SAFE, so we’ll see what the future holds.

                                                                                                            1. 1

                                                                                                              Java removed Thread.destroy() and Thread.stop(Throwable) in Java 11, only Thread.stop() is still only deprecated.

                                                                                                              It also deprecated some of the most basic constructors for removal in Java 17 (i. e. new Integer(...), new Double(...) etc.).

                                                                                                              Say what you want about Java, but they are regularly, but not lightly, removing things from it.

                                                                                                              1. 1

                                                                                                                Thanks, I meant Thread.stop. Glad to hear they are cleaning things up a little more aggressively now.

                                                                                                        1. 1

                                                                                                          For a simple job queue I reach for Beanstalkd. Fast, boring, just works.

                                                                                                          1. 4

                                                                                                            I think the point of the article is to stay away from additional infrastructure.

                                                                                                          1. 1

                                                                                                            I really hope they avoid second system syndrome because those changes sound pretty massive.

                                                                                                            1. 12

                                                                                                              Fuck, Lenna? Could we stop alienating women in tech? Don’t take my word for it, the AV1 folks are pleading with the field to stop using Lenna too.

                                                                                                              “If a professor makes a sexist joke, a female student might well find it so disturbing that she is unable to listen to the rest of the lecture. Suggestive pictures used in lectures on image processing are similarly distracting to the women listeners and convey the message that the lecturer caters to the males only. For example, it is amazing that the Lena pin-up image is still used as an example in courses and published as a test image in journals today.” ~D. P. O’Leary, 1999

                                                                                                              1. 6

                                                                                                                Yeah I always find it uncomfortable to keep seeing this same image. It goes back to college times in computer graphics class. I didn’t know why back then, but now I do. Btw, the professor back then even suggested we search the full pic after class.

                                                                                                                It’s about time we use other images in place of lenna.

                                                                                                                1. 4

                                                                                                                  the professor back then even suggested we search the full pic after class

                                                                                                                  🤮

                                                                                                                  1. 6

                                                                                                                    Speaking as a woman here, I honestly didn’t get the problem with the image; I thought she might just be wearing a shoulderless outfit or something. Then this comment prompted me to search the full image, and… oh, it’s a fucking Playboy pinup. Yeah.

                                                                                                                2. 3

                                                                                                                  Suggestive, is the crux of it. The pretext of sex in the image requires an investment in identifying the image.

                                                                                                                  Lenna is technical.

                                                                                                                  From a technical standpoint, apropos Imaging systems, identification and composition algorithms, and so on: Lenna is industrial.

                                                                                                                  Alas, we might ought to have used the Mona Lisa or some other such classic art, perhaps dismantled and re-assembled, over time, as ‘treasure’. Lenna is truly a beautiful pic, seeing her everywhere deep in the binaries is .. indeed .. a treat.

                                                                                                                  However, there are also rainbows.

                                                                                                                  1. 5

                                                                                                                    seeing her everywhere deep in the binaries is .. indeed .. a treat.

                                                                                                                    Lenna is also the male gaze; that’s why it’s problematic. https://en.wikipedia.org/wiki/Male_gaze

                                                                                                                  2. 3

                                                                                                                    We really need to move away from the pic in this industry.

                                                                                                                    There’s this wonderful tool, https://rawpixels.net. It’s so useful when working with raw images. But I really don’t feel comfortable using it at work, because the default image is the Lenna photo, and I don’t feel comfortable with suggestive pictures of naked women on my screen in an open floor plan office setting.

                                                                                                                    1. 2

                                                                                                                      Here are some alternatives (both PDF articles).

                                                                                                                      1. 1

                                                                                                                        I like the pic of Fabio in the second one. Because Fabio.

                                                                                                                    1. 38

                                                                                                                      “The Gang Builds a Mainframe”

                                                                                                                      1. 28

                                                                                                                        Ha ha! I don’t think the mainframe is really a good analogue for what we’re doing (commodity silicon, all open source SW and open source FW, etc.) – but that nonetheless is really very funny.

                                                                                                                        1. 7

                                                                                                                          It makes you wonder what makes a mainframe a mainframe. Is it architecture? Reliability? Single-image scale-up?

                                                                                                                          1. 26

                                                                                                                            I had always assumed it was the extreme litigiousness of the manufacturer!

                                                                                                                            1. 3

                                                                                                                              Channel-based IO with highly programmable controllers and an inability to understand that some lines have more than 80 characters.

                                                                                                                              1. 1

                                                                                                                                I think the overwhelming focus of modern z/OS on “everyone just has a recursive hierarchy of VMs” would also be a really central concept, as would the ability to cleanly enforce/support that in hardware. (I know you can technically do that on modern ARM and amd64 CPUs, but the virtualization architecture isn’t quite set up the same way, IMVHO.)

                                                                                                                                1. 2

                                                                                                                                  I remember reading a story from back in the days when “Virtual Machine” specifically meant IBM VM. They wanted to see how deeply they could nest things, and so the system operator recursively IPL’d more and more machines and watched as the command prompt changed as it got deeper (the character used for the command prompt would indicate how deeply nested you were).

                                                                                                                                  Then as they shut down the nested VMs, they accidentally shut down one machine too many…

                                                                                                                                  1. 2

                                                                                                                                    Then as they shut down the nested VMs, they accidentally shut down one machine too many…

                                                                                                                                    This sounds like the plot of a sci-fi short story.

                                                                                                                                    1. 3

                                                                                                                                      …and overhead, without any fuss, the stars were going out.

                                                                                                                              2. 1

                                                                                                                                I’d go with reliability + scale-up. I’ve heard there’s support for like, fully redundant CPUs and RAM. That is very unique compared to our commodity/cloud world.

                                                                                                                                1. 1

                                                                                                                                  If you’re interested in that sort of thing, you might like to read up on HP’s (née Tandem’s) NonStop line. Basically at least two of everything.

                                                                                                                                2. 1

                                                                                                                                  Architecture. I’ve never actually touched a mainframe computer, so grain of salt here, but I once heard the difference described this way:

                                                                                                                                  Nearly all modern computers from the $5 Raspberry Pi Zero on up to the beefiest x86 and ARM enterprise-grade servers you can buy today are classified as microcomputers. A microcomputer is built around one or more CPUs manufactured as an integrated circuit. This CPU has a static bus that connects the CPU to all other components.

                                                                                                                                  A mainframe, however, is built around the bus. This allows not only for the hardware itself to be somewhat configurable per-job (pick your number of CPUs, amount of RAM, etc), but mainframes were built to handle batch data processing jobs and have always handily beat mini- and microcomputers in terms of raw I/O speed and storage capability. A whole lot of the things we take for granted today were born on the mainframe: virtualization, timesharing, fully redundant hardware, and so on. The bus-oriented design also means they have always scaled well.

                                                                                                                            1. 3

                                                                                                                              The one key thing this blog post is missing: “but why?”

                                                                                                                              1. 3

                                                                                                                                Following one of the article’s links leads to Go issue 395 which contains the following motivation statement:

                                                                                                                                One motivation for doing this is that using an array pointer allows the compiler to range check constant indices at compile time.

                                                                                                                                a function like this:

                                                                                                                                func foo(a []int) int { return a[0] + a[1] + a[2] + a[3]; }

                                                                                                                                could be turned into:

                                                                                                                                func foo(a []int) int { b := a.[0:4]; return b[0] + b[1] + b[2] + b[3]; }

                                                                                                                                allowing the compiler to check all the bounds once only and give compile-time errors about out of range indices.

                                                                                                                                1. 5

                                                                                                                                  That’s five years old.

                                                                                                                                1. 2

                                                                                                                                  When I was a Rails developer I never wrote view-specific tests and don’t think they are especially useful.

                                                                                                                                  But I always wrote integration tests which exercised the full request/response cycle, including view rendering, which is critically useful. ERB is like any other piece of code: if you aren’t exercising it regularly, it’s probably broken.

                                                                                                                                  1. 1

                                                                                                                                    Controller unit tests (if that’s your jam) can also enable view rendering (off by default)

                                                                                                                                  1. 24

                                                                                                                                    Despite not having any kernel developers on-staff, Ars was able to verify at least some of Donenfeld’s claims directly, quickly, and without external assistance.

                                                                                                                                    Extremely important paragraph IMO. Why don’t we see things like this in other programming reporting?

                                                                                                                                    1. 16

                                                                                                                                      Because reporters earning $40k/yr don’t typically have the same skill set as a developer making $150k? If you know how to use grep well, you’ve got the start of a newer, higher paying career.

                                                                                                                                    1. 1

                                                                                                                                      Meanwhile 70 million downloads of a gem with transitive AGPL dependencies: https://rubygems.org/gems/mini_magick

                                                                                                                                      1. 1

                                                                                                                                        Did you report the issue?

                                                                                                                                        1. 3

                                                                                                                                          What’s the issue? You can probably build imagemagick without ghostscript, you can buy a license or your can follow the AGPL and give your users rights to examine and modify the software they use.

                                                                                                                                          This is something users will have to bring up if they use proprietary rails apps that process PDF or PostScript files. It’s a little disingenuous to license that gem as MIT but I have low expectations of license honesty these days :-(

                                                                                                                                          1. 2

                                                                                                                                            It uses those libraries by executing them as sub processes.0 That doesn’t trigger any *GPL licensing. That’s why I’m asking you to explain your comment.

                                                                                                                                            1. 1

                                                                                                                                              IANAL but one of the features of the AGPL is to close some of those holes with how users interact with the software and how developers link the software.

                                                                                                                                              1. 2

                                                                                                                                                The AGPL’s extra clauses kick in if you do both of:

                                                                                                                                                1. Modify the original software, and
                                                                                                                                                2. Make it accessible to users over a network

                                                                                                                                                The (A)GPL family of licenses historically have claimed a lot of things as derivative that maybe wouldn’t quite hold up in a court, but as far as I know they’ve never tried to claim that they can reach across process boundaries/IPC.

                                                                                                                                      1. 2

                                                                                                                                        Note this is over a year old. Ruby 3.0 contains the JIT but I don’t believe it can run Rails yet.