Threads for bigdubs

  1. 1

    I get the argument that using an encapsulating mutex is safer for guarding against mutations on a reference, I think the author misses one separate situation where that api is awkward, specifically if the critical section spans individual mutations. For that you will want a whole grain lock/unlock pattern, and specifically something like go’s defer keyword to be confident you’ll safely release regardless of what happens.

    People reading this are misunderstanding what I mean by “awkward”; what I mean here is that there is another field you have to add as the syncroot for the mutex, in addition to the mutex, if you’re guarding something that isn’t strictly mutating a single field.

    1. 15

      I may be misunderstanding, but the Rust API supports that — you acquire the guard object, make multiple changes to the data through it, and the mutex is automatically unlocked when it goes out of scope.

      I’ve implemented this same design in C++ and it works very well. It’s safe, efficient, and very easy to use. (In C++ the trick is to explicitly delete the copy and move operations on the guard object that’s returned from the lock call, so there’s no way to extend its lifespan.)

      1. 4

        Can you provide an example of such code? Because I cannot think about a case when Rust design would lack anything (and MutexGuard is exactly the same as Go’s defer just without need for developer to write it explicitly).

      1. 0

        Unrelated but the name reminded me of the (now delisted) exchange traded fund TVIX

        1. 3

          One of my big hopes with generics in 1.18 is JSON encoding / decoding gets faster because we can use concrete types and not use reflection (obviously this will take time as the stdlib will be mostly generics-free for some time).

          The encoding/json performance problems in the go standard library are a major issue, not insurmountable though.

          My suggestion to the author is to try and non-stdlib / optimized JSON unmarshaler.

          1. 3

            That’s not going to happen. The way generics work doesn’t allow for compile time execution (or even specialization, although that will probably happen eventually), so there’s no way serialization will ever work with Go generics. For the foreseeable future, if you want to use a concrete type when serializing, it will need to be go:generated.

            1. 3

              Yes, it’s likely that JSON unmarshaling is a performance bottleneck here. For “big data” JSON filtering, this is a real concern. I saw https://github.com/bytedance/sonic just the other day, and I know there are other performance-focused JSON libs.

              That said, I think it’s a stretch to say the “the encoding/json performance problems in the go standard library are a major issue”. For many common use cases like web applications it just doesn’t matter much. I’ve used Go’s encoding/json extensively for small servers as well as reasonably high-throughput servers (10s or 100s of requests per second, not thousands or millions) and it works fine – database query performance was usually the bottleneck.

              1. 2

                The share of issue depends on how much your program is doing in each area; if your program is just processing json, and the json library is slow, it’s an issue (as in, this case).

                The other piece of context here is how the performance is “relatively” to other runtimes; here is where the standard library implementation suffers the most, as compared to other common runtimes it’s significantly slower.

                1. 2

                  What other common runtimes are significantly faster than Go, and in which dimensions? As far as I’m aware, Go’s runtime, which is optimized for latency, is as fast or faster than anything on the market, but I’d be happy to see data suggesting otherwise!

                  1. 2

                    Sorry should have been clearer, *runtime standard library json packages. The terminology (“runtime”) there was used poorly.

                    1. 1

                      Gotcha! Thanks.

            1. 4

              I like that he still wants some experimentation from the official source of the software. This could help avoid jquery-fication. It says - yes, it will be in the core, so the ecosystem doesn’t become go+ben’s-generics, go+bob’s-generics, etc.

              1. 7

                Yeah, that’s the first thing I was afraid of. If the Go devs don’t provide something, then someone will, it’ll get used in production, it’ll become a de-facto standard (or maybe a couple competing ones), and then there will be a migration hassle and a lot of contention when core inevitably decides to do something quite different (e.g. glide & vgo vs. Go modules… modules are better, but launching them was still a hassle). Maybe having an official WIP repo will damp that down a little bit.

                1. 1

                  I think it’s likely they start putting golang.org/x/ packages together that use generics early and then move them in when they’re mostly stable.

                  1. 2

                    Unless I misread, that’s the plan described in the GitHub issue?

              1. 35

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

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

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

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

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

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

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

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

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

                                                          DHCP is a protocol that lets machines on a network discover what config they should use by shouting aimlessly at everyone on the network until someone tells them what they want.

                                                          Is a great description of DHCP.

                                                          1. 11

                                                            I’ll be sure to let the person I shamelessly stole that description from know that! She’ll probably be ecstatic to know her shitpost hit the mark.

                                                            EDIT: she was

                                                          1. 26

                                                            I find the ‘I need to edit in a web browser’ argument pretty weak.

                                                            I run a static website. It’s repository is currently hosted on GitLab GitLab has a web interface to edit files. Changes are automatically tested and pushed to the public through CI. And best of all, as I use markdown I usually prefer to edit in Vim, but I can use a million other tools if I’d like.

                                                            I’m not too sure about this workflow on an iPad, but I’m sure it isn’t as bad as the article author states for a static website.

                                                            1. 15

                                                              GitHub also allows you to edit, preview, and commit directly from their web UI. So no, I don’t buy the argument either.

                                                              1. 5

                                                                If he really wanted the pragmatic approach on iPad, he could’ve used Working Copy app, which allows you to edit your code and push it up to your Git repo. Then at this point he could have the setup that is described above, where it’s all automated.

                                                                1. 3

                                                                  Another aspect that’s important with a setup like this is having a deploy pipeline keyed off changes to the master branch.

                                                                  Between github/gitlab webui PR authorship, and circleci deploying the changes, we don’t need a webui either for our static blogs.

                                                                  1. 2

                                                                    does GitHub have CI pipelines? because you would need to create a CI pipeline to deploy changes from your repo to production in order for the web UI to be usable for this use case.

                                                                    1. 3

                                                                      I don’t use their CI, but apparently yes they do have this.

                                                                      For a team blog I’m working on at the moment, I’m using GitHub’s GitHub Pages mechanisms to automatically deploy whatever is on the gh-pages branch of the blog’s repository. It’s free, it’s easy, and it works.

                                                                      1. 1

                                                                        Yeah, it’s not as robust as GitLab’s but is fairly easy to set up. I was able to go from never using actions to having a commit trigger build and FTP everything over in about two hours [0] and most of that was figuring out sftp command line quirks between Mac, Ubuntu and my host.

                                                                        [0] http://prepend.com/setup/2019/12/figuring-out-actions.html

                                                                      2. 1

                                                                        I was able to teach a retired journalist to use this workflow (and Markdown) without much trouble. The website was simple, he had a lot of time on his hands, and he was eager to learn.

                                                                      3. 10

                                                                        Agreed, compared to that workflow my argument in regards to using a web browser is weakened. I’ll edit the post to reflect that. Thanks for the feedback.

                                                                        1. 8

                                                                          I think there is still an important point in that argument. The only alternatives that have been presented have been ad-hoc solutions like a headless CMS – yet another separate component that you need to setup – or GitHub/GitLab’s in-browser editing – yet another external service that you need to rely on. With an actual CMS like WordPress, you have a single consistent interface that you can totally own and control yourself.

                                                                          1. 1

                                                                            That’s true, thanks.

                                                                        2. 5

                                                                          I don’t think this is an easy option for everyone. You still have to know a thing or two about git, github/gitlab, and continuous integration. It might be easy for you, but it’s not easy for everyone. You wouldn’t need to learn an insane amount of stuff, but I imagine it’s still more work than using WordPress.

                                                                        1. 4

                                                                          i use tailscale to network my home computers (media server, battle station) and my work computer and my phone and it works flawlessly; highly recommended.

                                                                          one key has been setting up auto dns for the machines based on ${hostname}.vpn.my.tld

                                                                          1. 2

                                                                            I had been fiddling with this DIY on wireguard but now with this shelter in place order I’m always on my home network so the urgency has diminished.

                                                                          1. 9

                                                                            while the standard libraries don’t look excessive either.

                                                                            Honestly, if you want the killer golang feature, this is it. The standard library is comprehensive for the wheelhouse golang use cases, and you don’t have to build much to get going. Anything you do end up building usually are convenience packages for standard library primitives.

                                                                            1. 6

                                                                              It’s hard to overemphasize your excellent point. I build a quite complex background job server in Go and my dependency graph is tiny compared to most any other programming ecosystem:

                                                                                      github.com/BurntSushi/toml v0.3.1
                                                                                      github.com/benbjohnson/ego v0.4.0 // indirect
                                                                                      github.com/go-bindata/go-bindata v3.1.2+incompatible // indirect
                                                                                      github.com/go-redis/redis v6.15.7+incompatible
                                                                                      github.com/justinas/nosurf v1.1.0
                                                                                      github.com/stretchr/testify v1.3.0
                                                                              

                                                                              TOML, Redis, some web and test utilities. That’s it, everything else is stdlib. This saves me a huge amount of maintenance work by avoiding dependent version upgrades.

                                                                              1. 2

                                                                                I am not familiar with the Go ecosystem, but I remember noodling around with Python in 2006 or so. Back then, people were saying, “isn’t it great how much stuff is in stdlib?”. These days, I have heard that the stdlib is where libraries “go to die” (everyone moves onto more idiomatic libs developed as the ecosystem matures, and the stdlib stuff never gets fixed due to lack of interest and/or backwards-compat concerns).

                                                                                What are your thoughts on this dynamic? Is it an inevitable part of a language’s lifecycle if it attempts a batteries-included stdlib (particularly because things that enter stdlib early get pinned down before language idioms stabilise)? Has Go avoided this problem, or just not hit it yet?

                                                                                1. 1

                                                                                  Go has avoided this problem (mostly!) by being very conservative about what APIs go into the stdlib.

                                                                                  There are still a few mistakes that made it in, but this is largely achieved by taking people with 40+ years experience and giving them enough time and space to apply their judgement carefully.

                                                                            1. 5

                                                                              We are currently doing a mandatory WFH test run where our office is closed today and everyone is working from home. So far it’s been interesting, lots of zoom meetings (context: I work for Blend, our SF office is around 300 people).

                                                                              We are also allowing people to electively WFH for the foreseeable future.

                                                                              1. 10

                                                                                Go you! So many places are all “I guess we’ll deal with it when it happens”, but there’s nothing like a test run.

                                                                                1. 2

                                                                                  Similar. I work from home normally though, but part of a big office in London. We’ve been rotating departments the last week, each department testing their team working from home. We’re in public health though so we’re trigger happy mitigating anything that will mess with business continuity.

                                                                                  1. 2

                                                                                    I’m in ops, and our WFH game is 100% cos we have to be able to do our entire job from a laptop as needed when on call. Our devs are not on call, but they are similarly well set-up.

                                                                                    The rest of the company is being dragged into the present quite nicely! We have a shiny new OpenVPN setup that’s doing the job of connection.

                                                                                    The sticking point is phone meetings - suitable software (RingCentral sorta sucks; Google Hangouts really sucks; Slack’s audio is way better, but only tech is on Slack), and having the people in the room give a damn about making sure the microphone can hear them.

                                                                                    1. 3

                                                                                      Zoom any good? Their name seems to crop up in this context a lot.

                                                                                      1. 1

                                                                                        Zoom has been excellent the few times I’ve used it this year – far above all other solutions I’ve experienced besides Blue Jeans (I’d say they’re tied for top of the heap).

                                                                                        1. 1

                                                                                          RingCentral is actually a fork of Zoom, I think. I’ve only used Zoom myself for podcast recording, and it was fine?

                                                                                          1. 2
                                                                                    1. 34

                                                                                      Disallowing import cycles. This really limits how useful packages are for modularising a project, since it encourages putting lots of files in a package (or having lots of small packages, which can be just as bad if files which should be together are not).

                                                                                      Maybe I’m in the minority here but this has forced me to design packages in a better / more modular fashion that really shows up later in a projects lifecycle in spades.

                                                                                      1. 34

                                                                                        I agree, every import cycle I’ve seen has been a mistake of design.

                                                                                        1. 23

                                                                                          The same restriction actually applies to Rust. You can’t have import cycles between crates, which are Rust’s compilation units. Rust modules are an extra tool for code organization within a crate that really has no Go equivalent, and recursive imports in this case are occasionally useful.

                                                                                          A real comparison here is difficult to make, since in Rust, you might not create as many crates as you would packages in Go. But it’s pretty likely that you’ll create some.

                                                                                          It’s also further complicated by the fact that a Go module is analgous to a Rust crate in terms of the unit of distribution, with the crucial distinction that a Rust crate is also a compilation unit. But in Go, a module may of course be built from many compilation units.

                                                                                          1. 3

                                                                                            Technically, I think it’s actually possible to work around this by using the dot alias in the import.

                                                                                              1. 3

                                                                                                Yeah, I know it’s frowned upon (with good reason because circular deps are a bad idea). I was merely pointing out that it is possible :)

                                                                                          1. 4

                                                                                            Avoid package level state

                                                                                            I really actually like this way of declaring this goal. I’ve heard “no package level variables” before, but there are instances you might actually want to do this (regexp.MustCompile comes to mind).

                                                                                            This being said, there are still instances where init/package level state are useful (in particular, systems where you can register drivers or plugins, similar to the database/sql package.

                                                                                            1. 4

                                                                                              I might be the odd man out, but I really dislike the database/sql interface. Unless I’m missing some hidden advantage of the init() method, I would think it better to have at least a package-level RegisterDriver() function if not a type DriverSet struct{} and a func (ds *DriverSet) RegisterDriver(). Thoughts?

                                                                                              1. 3

                                                                                                With vendoring init() and registering a driver by accident twice is a sign imho that the pattern is fraught, I would also rather have a method I have to call and make it explicit in my main()

                                                                                              2. 2

                                                                                                There are still instances where init/package level state are useful (in particular, systems where you can register drivers or plugins, similar to the database/sql package.)

                                                                                                Like weberc2 I consider this an antipattern. It’s strictly better to have a component that takes a driver as a parameter to construction.

                                                                                                1. 1

                                                                                                  I understand where you’re coming from. In an ideal world I would agree, but I still think this can be a useful pattern if you need things configurable at runtime.

                                                                                                  One of the examples I have of this is my IRC bot - everything is implemented as a plugin and they’re all registered by name. When a bot is started, it takes the list of all the plugins and initializes them based on that list… this would be a pain to do by hand. Similarly, with databases, if you’re supporting more than one, it’s hard to configure at runtime if there are multiple possibilities without a system like this (though you need to special case a number of things as well because of query incompatibilities).

                                                                                              1. 3

                                                                                                Go is not single threaded by default in versions after version 1.5. GOMAXPROCS governs this, and it is configurable, and defaults to the number of CPUs available.

                                                                                                1. 4

                                                                                                  Sorry, I meant that unless you use goroutines, Go is single-threaded. I’m imagining a programming language that even the most basic primitives are all multi-threaded.

                                                                                                  1. 2

                                                                                                    Goroutines are basic primitives in Go. That’s the point of the thing.

                                                                                                    1. 7

                                                                                                      Right, which is why I specifically called out Go as being close. That being said, Go’s concurrency is still opt-in, as in I have to specifically tell go “hey, this section right here, distribute it across multiple cores” as opposed to Go detecting that a particular piece of code can be run across multiple cores without my telling it.

                                                                                                    2. 1

                                                                                                      Kind of depends what you’re writing; Golang is very good at making you not realize you’re on a separate stack/goroutine from the entry point to prevent blocking and the like.

                                                                                                      An example of this is net/http each request is on it’s own routine (which is its own can of worms), but to the view of your caller it’s just a function you write, you don’t ever have to type go ... the standard library does it for you.

                                                                                                      But yes, you have to explicitly kick out your own goroutines for parallel processing but there are a lot of primitives to help with this (i.e. channels) and doing so requires you to think through the implications (memory usage) so IMHO it’s a fair trade-off.

                                                                                                  1. 44

                                                                                                    Interesting, but I feel it could have stopped at “it’s smaller”. That’s the overwhelming difference IMO.

                                                                                                    1. 12

                                                                                                      And I think they address that by bringing up the invite system which will naturally limit the growth of the site.

                                                                                                      There was an HN comment on this that, I think, rightfully called out the downside of this that you don’t get as many random domain experts adding meaningful comments that get sorted to the top by voting.

                                                                                                      I would still prefer the smaller, more civil community and hope we can invite domain experts and the like over time.

                                                                                                      1. 16

                                                                                                        Agreed. Having a smaller community doesn’t mean it has to have the same composition of people, “just fewer of them”.

                                                                                                        I think Lobsters has done extraordinarily well in attracting domain experts while keeping out the valley-style surveillance capitalist blockchain AI expert “investors”. Let’s keep it that way!

                                                                                                        1. 14

                                                                                                          Not to mention that Lobsters discourages any non-tech posts, especially the culture war related ones.

                                                                                                          1. 22

                                                                                                            True.

                                                                                                            Reading some stuff on HN felt like a weird civil war between the I-got-my-economy-degree-from-Ayn-Rand camp and the I’m-continously-looking-for-reasons-to-be-offended-and-I’ll-make-it-your-problem camp, whose only common nominator was their despise of the poor, the weak and the people not living in SV; usually caused by some silly clickbait non-tech article that would never have gotten posted on Lobsters.

                                                                                                            1. 6

                                                                                                              This entire article is naval-gazing meta nonsense that I’ve flagged as off-topic and yet it’s still at the top of the front page. So I’m not sure you’re correct.

                                                                                                              1. 1

                                                                                                                I don’t disagree, but we do have the meta tag.

                                                                                                                As long as we can avoid descending into a self-congratulatory circlejerk I think there could be some benefit to it.

                                                                                                                1. 1

                                                                                                                  At least its only one category and I think it’s an acceptable “necessary evil”. I filter it out in my feed and just search “tag:meta” every so often to see what’s going on in the meta.

                                                                                                          2. 3

                                                                                                            I think it’s also important there’s a way to get invites without knowing people but it requires a small amount of effort and knowledge of irc.

                                                                                                            If it was purely invite only, that would be a big limitation by having only a friends of friends effect.

                                                                                                            What I liked the most about the internet when I joined is because there was a “proof of work” required, the population tended toward people with some sort of shared mindset. I like that, but don’t want to be arbitrarily difficult.

                                                                                                            1. 2

                                                                                                              I think the biggest downside of the invite system is how much it limits access to anyone who doesn’t have a low Erdos number to the guy who founded the site. The note to show up in the chat room is a vital second route.

                                                                                                              1. 1

                                                                                                                rightfully called out the downside of this that you don’t get as many random domain experts adding meaningful comments that get sorted to the top by voting.

                                                                                                                If like those, put an email address or site with contact form into your profile. They sometimes contact me about Lobsters comments that way. That’s a mix of some that I saw on HN and some that don’t post on either.

                                                                                                            1. 1

                                                                                                              Not all situations are the same, sometimes bool is all you need and it’s better to keep things simple.

                                                                                                              One example of a bool being swapped out for a different value is “Expired”; you can represent that as a timestamp of when, which then also includes the binary state of expired or not.

                                                                                                              Overall though, sweeping generalizations around some facet of programming aesthetics are incredibly counterproductive and the time is better spent understanding the trade offs of the different tools a language gives you.

                                                                                                              1. 3

                                                                                                                Meh, normally, I’d use

                                                                                                                enum CacheState { Fresh, Expired }
                                                                                                                

                                                                                                                Yeah, it’s a bit more complicated to branch on it, but it’s more robust for all the reasons given in the OP.

                                                                                                                1. 1

                                                                                                                  So, part of this is I code day to day in a language that doesn’t support enums particularly well (golang), but part of it also is to replace a boolean you just created another type and two values of it, which you need to be able to parse and marshal, and generally keep track of and refactor later.

                                                                                                                  IMHO that’s better just left as a bool, and typically you just structure it such that the default value (typically false) is also the intended default for the intent of the field.

                                                                                                                  i.e. TLSSkipVerify bool where the default is to verify, set true to skip verification.

                                                                                                                2. 2

                                                                                                                  Overall though, sweeping generalizations around some facet of programming aesthetics are incredibly counterproductive and the time is better spent understanding the trade offs of the different tools a language gives you.

                                                                                                                  This is recognized in the second paragraph (and the first one is just 3 words):

                                                                                                                  With any blanket statements like this, there are always exceptions. Though in general, I believe the use of enums is often a better choice compared to boolean, unless you really need to squeeze your data into one single physical bit.

                                                                                                                1. 8

                                                                                                                  I’m still unconvinced contracts need to be strictly separate from interfaces. The argument that enforcing operators would be repetitive maybe falls flat on me because it seems trivial to ship the stdlib with some basic Operatable interfaces you can reach for, but also that doing a bit of extra typing for clarity I’ve generally seen as part of the golang ethos.

                                                                                                                  Similarly, the idea that you can never have discrete instances of contracts (versus interfaces) runs counter to how I’ve used generics in the past where generic constraints are just interfaces and you can reference the type constraint interface when declaring values later.

                                                                                                                  1. 6

                                                                                                                    Agreed on interface reuse. My guess is adding new semantics to interface is hard to back out of, where as “contracts” can just ultimately be deprecated when the dictators decide that the experiment “failed.”

                                                                                                                    OK, maybe that’s not fair. But, I agree that there’s a weird resistance to extend something that seems to really make sense, in favor of adding something completely new. Either way, 3rd party tooling will be broken until updated…

                                                                                                                    1. 2

                                                                                                                      They extended functions and types to accept type parameters, but then they neglected to do the obvious thing which is extend interfaces with type parameters. Do that, then allow interfaces to be the specifiers in the type parameters list - done. They dedicated a whole section to this but every argument is unconvincing and evinces a lack of imagination. Just read this:

                                                                                                                      Contracts, unlike interfaces, support multiple types, including describing ways that the types refer to each other.

                                                                                                                      Then add type parameters to the interfaces.

                                                                                                                      It is unclear how to represent operators using interface methods.

                                                                                                                      Other languages either map operators to a special name or provide a syntax for the overloading. Most design documents have a prior art section - do your homework!

                                                                                                                      An interface is a type, not a relationship between function definitions and callers. A program can have a value of an interface type, but it makes no sense to speak of a value of a contract type.

                                                                                                                      Again, there is no creativity here or an attempt to see what other people have done. Expand the definition of interface. I would solve the problem like this: if an interface appears in a type parameter list, the type is unboxed and preserves its type, whereas if it occurs in a parameter list as a type, then it is the usual boxed interface. It is really that simple. This also happens to be nearly exactly what Rust did for a long time.

                                                                                                                      In other words, contracts are not extensions of interface types.

                                                                                                                      This is wrong. It’s wrong, it’s wrong, it’s wrong.

                                                                                                                      I will end this comment with just a little bit of polemic, which by now is par for most comments about Go but totally deserved: I do not trust the language designers. There is too much NIH syndrome, too much anti-intellectualism, too much reinvention of solved problems. It is a waste of a great runtime. Use something else.

                                                                                                                      1. 7

                                                                                                                        do your homework!

                                                                                                                        It seems manifestly obvious that they did, considering the design document cites numerous languages and how their design improves on past mistakes. Consider cutting back on your hyperbolic ranting and snobbery; it undermines your commentary.

                                                                                                                        1. 2

                                                                                                                          That comment was specifically about the preceding quotation.

                                                                                                                        2. 2

                                                                                                                          They extended functions and types to accept type parameters, but then they neglected to . . . extend interfaces with type parameters.

                                                                                                                          Although the draft doesn’t explicitly mention interfaces as a possible parameterized type, I don’t see anything that would imply they aren’t supported.

                                                                                                                      1. 2

                                                                                                                        UPDATE

                                                                                                                        They’re removing this tracking according to the CEO:

                                                                                                                        https://twitter.com/rahulvohra/status/1146539948276740096

                                                                                                                        1. 17

                                                                                                                          It’s nice to read the Etsy story from the author. Also, his point is something I also agree with, having gone through similar product lifecycles (from creating something new and fun to maintaining and iterating on it). The main takeaway from these slides for me is this:

                                                                                                                          Software that’s been around longer tends to need less care and feeding than software that just came out.

                                                                                                                          This, a thousand times. Once you worked with a mature piece of technology in a domain, you get to relate and compare to it. A great example at my recent company is Go. We have two camps of engineers: ones who want to use Go and those who vote for Java. The main argument for the Java folks was the maturity of the tooling and environment.

                                                                                                                          Some teams chose Go. Some did Java. A few years down the road with services in production, the Go teams started to realise the gap they had in tooling, standard libraries and the lot compared to teams working in Java. Some teams migrated to Java, but most of them are just spending a bunch of time building these tools from scratch or contributing to existing solutions, to add the support.

                                                                                                                          There’s nothing good or bad, choosing new and different technologies. But it’s good to take the additional effort and additional learning into consideration when doing so - and in many cases, this might actually be a reason to choose a new technology over an existing one!

                                                                                                                          1. 12

                                                                                                                            What gaps did the teams run into with Go?

                                                                                                                            1. 7

                                                                                                                              The biggest limitations we have found were maturity of toolchains and the availability of high-quality libraries in Java that were not there with Go a few years ago. Both have nothing to do with the language and everything to do with the maturity of the ecosystem.

                                                                                                                              For example, Java has excellent tooling for IDE integration, refactoring, static analysis, garbage collection analysis. Debugging I’m production has strong tooling support. Go is catching up in these areas.

                                                                                                                              Stream packages like RxJava, high-performance networking libraries like Netty, inter-threading libraries like Disruptor were readily available and important to some services that decided to go with Java. Again, a lot of teams/services either did not need these or considered the lack of them no dealbreaker when going with Go, considering some of the other upsides, like the canonical style and the strong community and growth around it.

                                                                                                                              Most of my points were for Go 2-3 years ago. The ecosystem is growing fast, libraries and tools becoming more mature. But this approach will be true for the next “new” language or framework a team picks - which may not even exist today!

                                                                                                                              1. 6

                                                                                                                                We’ve run into situations with inconsistent quality with ecosystem libraries (lots of breaking changes requiring aggressive vendoring / forking), or just not having an equivalent library.

                                                                                                                                One example until recently was a MongoDB driver (this is, itself, probably worth scrutiny in the first place), also libraries for working with PDFs. Some tooling for AWS Kinesis is kludgy on their go-sdk or just missing features.

                                                                                                                                For the vast majority of what you need to do we haven’t had too much we needed to roll custom compared to java though.

                                                                                                                              2. 2

                                                                                                                                Completely agree. I include this right in the interview screen and job descriptions. Doing so has helped both our organization and the prospective applicants, because some people want to work on the bleeding edge. They’re not going to be thrilled working in our team, where we try to stick with “boring” tech choices.

                                                                                                                              1. 11

                                                                                                                                I too was once an awesomewm user (on Arch Linux) for a while, but I stopped around 7 years ago because even after investing tens to hundreds of hours in setting up my fully featured environment, it wasn’t stable. It was hard to keep the system up to date and working.

                                                                                                                                These days on macOS I can simulate my awesomewm days with Chunkwm and ubersicht and on top of that WiFi works, sleep works, my battery life is great! I can still work with a non broken package manager because of the nix package system and it’s reproducible. Having said that, of course I wish I were using Linux (these days I’d go for Nixos), but I value not having to deal with the sysadmin stuff unexpectedly.

                                                                                                                                1. 3

                                                                                                                                  Similarly, but not quite, I use a windows PC I built at home with vmware which manages an ubuntu install with i3. You get (some) of the benefits of a real development environment (and the operational stability of windows) and i3 for tiling, but the downsides are some mystery key combinations get captured by windows and it never really feels fully operational.

                                                                                                                                  Plus side is you can just create a new vm when things break or you want to try out something else like elementary or arch.

                                                                                                                                  1. 1

                                                                                                                                    I was just thinking about this in the morning and I realized that my troubleshooting incident rate isn’t really higher on Linux than it is on Windows or OS X. What I actually want to say is: it is always implied that on Linux something will break and you’ll spend a good chunk of time fixing it, but I have the same issues on Windows and OS X at more or less the same frequency and the time spend on it.

                                                                                                                                  1. 1

                                                                                                                                    Go has pretty good built in facilities for documentation, we just point godoc.org at our repos.