1. 2

    Next in the series, why you should not use std::unique_ptr

    1. 1

      Pretty basic.

      It’s a cheap Dell 4k hooked up to my work MBP; the other keyboard and mouse are connected to the big Windows box under the desk.

      1. 2

        I’m afraid Kinesis advantage keyboard cannot be qualified as basic :)

        1. 1

          Fair! The Mac is running 11.1 and the big box under the desk, Windows 10.

      1. 6

        This question was prompted by a discussion I had about how I felt like all the momentum in programming languages is pointing toward Rust these days, and I felt like there’s no point in keeping my Go current (it’s been languishing for a couple of years now anyway).

        So, I asked this question to see (among other things) if I’m right or wrong.

        1. 12

          What is driving that feeling? Genuinely curious, because I feel the opposite. I am seeing more and more enterprises adopt Go. In conversations I have with other engineers, Rust still feels a little underground.

          I also think that Go and Rust have slightly different use cases & target audiences.

          1. 9

            Well, lobste.rs, for one. I feel like everywhere I look on here people talk about how they’d re-do everything in Rust if they could. The number of Rust advocates I see here seems to dwarf the number of Go advocates. Maybe that’s perception because Rust is “newer” and its advocates louder, but who knows.

            The things that really stuck with me, though, were Linus indicating that he’d be open to allowing Rust in the kernel, Microsoft starting to switch to Rust for infrastructure, and Dropbox migrating their core technologies to Rust.

            I just don’t see stories like that for Go. I don’t know if I’m not looking in the right place, or what.

            1. 22

              Go and Rust more or less solve the same problem (although the overlap isn’t 100%), just in different ways, not too dissimilar to how Perl and Python more or less solve the same problems in very different ways.

              I have the impression that, on average, Go tends to attract people who are a little bit jaded by the Latest Hot New Thing™ churn for 20 years and just want to write their ifs and fors and not bother too much with everything else. This is probably one reason why the Go community has the (IMHO reasonably deserved) reputation for being a bunch of curmudgeonly malcontents. These are not the sort of people who go out and enthusiastically advocate for Go, or rewrite existing tools in Go for the sake of it: they’re happy with existing tools as long as they work.

              Another reason I don’t really like to get involved in Go discussions is because some people have a massive hate-on for it and don’t shy away from telling everyone that Go is stupid and so is anyone using it every chance they get. It gets very boring very fast and I have better things to do than to engage with that kind of stuff, so I don’t. There’s some people like that on Lobsters as well, although it’s less than on HN or Reddit. It’s a major reason why I just stopped checking /r/programming altogether, because if the top comment of damn near every post is “lol no generics” followed by people ranting about “Retards in Go team don’t think generics are useful” (which simply isn’t true) then … yeah… Let’s not.

              1. 14

                Go and Rust more or less solve the same problem

                Hard disagree, rust is way more useful for actual problems like c/c++ are. I can write kernel modules in it, there is almost no way i’d want to do that with go. Having a garbage collector, or even really a runtime in go means a different use case entirely to being able to run without an os and target minis. Yes I know go can be used for that too but just due to having a GC you’re limited on how far down the horsepower wagon you can go.

                I hold no views outside of that rust actually has solutions and community drive (aka people using it for that upstreaming things) for programming things like avr processors etc… I don’t hate go it just strikes me as redundant and not useful for my use cases. Kinda like if you learn python not much use for learning ruby too kind of a deal. And if I’m already using rust for low level stuff, why not high level too?

                I don’t however miss debugging goroutine and channel bugs though, go is way easier to shoot yourself in a concurrent foot without realizing it. It might be ‘simple’ but that doesn’t mean its without its own tradeoffs. I can read and write in it but prefer the rust compiler telling me i’m an idiot for trying to share data across threads to goroutine debugging where two goroutines read off one channel and one of ems never gonna complete cause the other already got it. I’m sure “I’m holding it wrong” but as I get older these strict and more formal/functional languages like rust/haskell/idris/blah strike my fancy more. I”m not talking about generics really but stuff like Monads (Option/Result essentially) read to me way better than the incessant if the thing i did isn’t nil constantly. Its closer to what I’ve done in the past in C with macros etc…

                Its not that I hate it though, just that the language seems a step back in helping me do things. Idris as an example though is the coolest thing I’ve used in years in that using it was like having a conversation with the compiler and relearning how to move my computation to the type system. It was impressive how concise you can make things in it.

                As a recovering kernel/c hacker, you’d think go would appeal but to be honest it just seems more of the same as c with less ways of stopping me from shooting myself in the foot needlessly.

                But to each their own, functional languages with types just strike me as actually doing a lot of things that OO languages from the mid 90’s always said could be done with open form polymorphism but never seemed to happen.

                In 10 years we’ll see where the ball landed in the outfield so whatever.

                1. 11

                  Yes, hence the “more or less”. Most people aren’t writing kernel modules; they’re writing some CLI app, network service, database app, and so forth. You can do that with both languages. TinyGo can be used for microcontrollers, although I don’t know how well it works in practice – it does still have a GC and a (small) runtime (but so has e.g. C).

                  I don’t however miss debugging goroutine and channel bugs though, go is way easier to shoot yourself in a concurrent foot without realizing it.

                  Yeah, a lot of decisions are trade-offs. I’ve been intending to write a “why Go is not simple”-post or some such, which argues that while the syntax is very simple, using those simple constructs to build useful programs is a lot less simple. In another thread yesterday people were saying ‘you can learn Go in two days”, but I don’t think that’s really the case (you can only learn the syntax). On the other hand, I’ve tried to debug Rust programs and pretty much failed as I couldn’t make sense of the syntax. I never programmed much in Rust so the failure is entirely my own, but it’s a different set of trade-offs.

                  In the end, I think a lot just comes down to style (not everything, obviously, like your kernel modules). I used to program Ruby in a previous life, which is fairly close to Rust in design philosophy, and I like Ruby, but it’s approach is not without its problems either. I wrote something about that on HN a few weeks ago (the context being “why isn’t Ruby used more for scripting?”)

                  1. 4

                    Most people aren’t writing kernel modules; they’re writing some CLI app, network service, database app, and so forth. You can do that with both languages.

                    CLI yes, database probably, but I don’t think Rust’s async or concurrency or whatever story is mature enough to say it’s comparable with Go for network services.

                    1. 1

                      Cooperative concurrency is just more complicated (as a developer, not as a language designer) than preemptive concurrency. The trade-off is that it’s more performant. Someone could build a Rust-like language, i.e. compiler-enforced data race freedom, with green threads and relocatable stacks. And someday someone might. For now, the choice is between performance and compiler-enforced correctness on the Rust side, or “simpler” concurrency on the Go side.

                2. 3

                  There’s just a lot of toxicity about programming languages out there, and subjectively it feels particularly bad here. Rust has a lot to like and enough to dislike (abandoned libraries, inconsistent async story, library soup, many ways to do the same thing), but something about its culture just brings out the hawkers. I still heartily recommend giving Rust a try, though you won’t be super impressed if you’ve used Haskell or Ocaml in the past.

                  1. 6

                    I came to Rust after having used Haskell and the main thing about it that impressed me was precisely that it brought ML-style types to language with no GC that you could write an OS in.

                    1. 5

                      with no GC

                      I guess I find this often to be a solution with very few problems to solve. It’s understandable if you’re writing an OS or if you’re working on something real-time sensitive, but as long as the system you’re making can tolerate > 1ms p99 response times, and doesn’t require real-time behavior, Go, JVM languages, and .NET languages should be good enough. One could argue that there exists systems in the 1-10ms range where it’s easier to design in non-GC languages rather than fight the GC, and I can really see Rust succeeding in these areas, but this remains a narrow area of work. For most systems, I think working with a GC keeps logic light and easily understandable. When it comes to expressive power and compiler-driven development, I think both Haskell and Ocaml have better development stories.

                      1. 1

                        Rust also has a much cleaner package management story and (ironically) faster compile times than Haskell. And first-class support for mutability. And you don’t have to deal with monad transformers.

                        Haskell is still a much higher level language, though. I experimented last night with translating a programming language core from Haskell to Rust, and I quickly got lost in the weeds of Iterator vs Visitor pattern vs Vec. Haskell is pretty incredible in it’s ability to abstract out from those details.

                    2. 0

                      Your descriptions of both advocates and Go haters match my experience exactly.

                    3. 14

                      I’ve been using Go since around the 1.0 release and Rust for the last year or so. I don’t think either of them is going away any time soon. Go has less visible advocates, but it’s definitely still used all over the place. Datadog has a huge Go repo, GitHub has been looking for Go engineers, etc.

                      Rust is more visible because it’s newer and fancier, but it still loses for me in multiple aspects:

                      • Development speed - It’s a much pickier language and is much slower to develop in, though it forces you to get things right (or at least handle every case). Rust-Analyzer is great, but still fairly slow when compared to a simpler language.
                      • Compilation speed - Go compiles way faster because it’s a much simpler language.
                      • Library support/ecosystem - Because Go has been around for quite a while, there are a wealth of libraries to use. Because Rust hasn’t been around as long, many of the libraries are not as mature and sometimes not as well maintained.

                      However, Rust makes a number of improvements on Go.

                      • Error handling - Rust’s error handling is miles above Go. if err != nil will haunt me to the end of my days.
                      • Pattern matching - extremely powerful. This is an advantage Rust has, but I’m not sure how/if it would fit in to Go.
                      • Generics - In theory coming to Go soon… though they will be very different feature-set wise

                      They’re both great languages, and they have different strengths. For rock-solid systems software, I’d probably look at Rust. For web-apps and services, I’d probably look to Go first.

                      1. 4

                        Rust also loses massively in concurrency model. Tokio streams is so subpar to channels.

                        1. 3

                          Tokio also has channels - MPSC is the most common variant I’ve seen.

                          When Stream is added back to tokio, these will also impl Stream

                          I do agree that having goroutines as a part of the language and special syntax for channels makes it much easier to get into though.

                          1. 1

                            Rust’s async/await is definitely more complicated than Go’s green threads, and is almost certainly not worth it if Go has everything you need for your project. However, Rust’s standard threads are extremely powerful and quite safe, thanks to the Sync and Send marker traits and associated mechanics, and libraries like rayon make trivial parallelism trivial. Just yesterday I had a trivially parallel task that was going to take 3 days to run. I refreshed myself on how to use the latest rayon, and within about 10 minutes had it running on all 8 hyperthreads.

                          2. 2

                            Spot on. They both have their annoyances and use cases where they shine.

                          3. 6

                            A further difference is that Go code is hard to link with other languages due to its idiosyncratic ABI, threading and heaps. Rust fits in better. Not just in OS kernels but in mobile apps and libraries. (I’m still not a fan of Rust, though; Nim fits in well too and just feels a lot easier to use.)

                            1. 1

                              I would say that is entirely compiler dependant, and not a property of the language Go. https://github.com/tinygo-org/tinygo

                              1. 3

                                As long as the language has highly scalable goroutines, it won’t be using native stacks. As long as the language has [non ref-counted] garbage-collection, it won’t be using native heaps.

                                1. 1

                                  Well, tinygo != go, and e.g. gccgo still reuses the official standard library from the main implementation (which is where lots of the frustrating stuff is located, e.g. the usage of raw syscalls even on platforms like FreeBSD where it’s “technically possible but very explicitly not defined as public API”).

                              2. 5
                            2. 9

                              Golang is awesome. It works without fanfare.

                              1. 8

                                As someone who dislikes Go quite a lot, and is really enjoying Rust: I think they are different enough they serve different use cases.

                                Go is much faster to learn, doesn’t require you to think about memory management or ownership (sometimes good, sometimes very very bad, Go code tends to be full of thread-safety bugs), is usually fast enough. For standard web app that is CPU-bound it’ll work just fine, without having to teach your team a vast new language scope.

                                On the flip side, I’m working on a LD_PRELOADed profiler that hooks malloc(), and that’s basically impossible with Go, and I also need to extract every bit of performance I can. So Rust is (mostly) great for that—in practice I need a little C too because of Reasons. More broadly, anytime you want to write an extension for another language Go is not your friend.

                                1. 4

                                  Go comes with a built-in race detector. What sources do you have for “tends to be full of thread-safety bugs”?

                                  1. 11

                                    As someone with a fair bit of go experience: the race detector only works on races you can reproduce locally, as it’s too slow to run in production.

                                    Rust stops you from doing things that can race; go gives you a flashlight to look for one after you accidentally introduce it.

                                    1. 1

                                      That is a good point, but once a developer has encountered the type of code that makes the race detector unhappy, will they not write better code in the future? Is this really a problem for most popular Go projects on GitHub, for instance? Also, the “staticcheck” utility helps a lot.

                                      1. 3

                                        Unfortunately, there’s still, even among some experienced programmers, a notion that “a race will happen so rarely we don’t have to worry about this one case”. Also I’ve seen an expectation that e.g. “I’m on amd64 so any uint64 access is atomic”, with no understanding of out-of-order execution etc. I assume in Rust this would be a harder sell… though the recent drama with a popular web framework (can’t recall the name now) in Rust seems to show to me that using unsafe is probably kinda similar approach/cop-out (“I just use unsafe in this simple case, it really does nothing wrong”, or “because speed”).

                                2. 3

                                  I think (hope) the world settles into Rust and Go. I don’t see the Bell Labs folks not going 3 for 3 with Go. Rust I enjoyed playing with many months ago and it was a bonus I guess (at the time) that it was backed by Mozilla. Misplaced loyalties abound. Maybe (in a decade or so) lots of things once written in C will Rust over and tcp/http stuff will be written in Go.

                                1. 4

                                  Gave an internal talk about our company no longer pushing for microservices, but instead, launching an internal serverless system where logically related routes are deployed independently as a lambda of sorts. A central team takes care of operations, like pushes. Maybe someday we’ll publish a tech blog about this.

                                  Worked on a quick newsletter on Go for Internal Services.

                                  Hopefully recording my first episode of SRE Podcast.

                                  Finally, baked a cake with one of my friends to celebrate Biden’s victory.

                                  1. 1

                                    Out of curiosity, why did you decide to push for lambdas instead of microservices? Do you have very irregular (or rare) load?

                                    1. 1

                                      They’re not lambdas in the AWS sense. What we did was wrap the existing Python controllers with gRPC, which made every controller an RPC service. Then we grouped these RPC services into logical components, and made each component its own deployment. And then we use Envoy to transcode http requests to gRPC.

                                      This gives us push independence (one route’s breakage doesn’t block the entire monolith’s push) and isolation. Gives us a bunch of benefits of microservices for “free”.

                                  1. 1

                                    Super busy at work these days, but I started working on my own debugger (because I’m sort of sick of using gdb). Hopefully will have some time to work on it.

                                    1. 8

                                      traveling to Denmark to spend the week in a remote house near the sea.

                                      pandemic prevented us from taking any kind of vacation. so, really looking forward to it.

                                      1. 2

                                        I did that about a month ago and it was great. Enjoy!

                                        1. 2

                                          this sounds wonderful!

                                          1. 1

                                            Which part of Denmark? My wife is danish, so I know well the zone where she come from (Central Jylland)

                                            1. 1

                                              Rømø :)

                                              1. 1

                                                I went there. It’s a very nice place. Let’s hope you can find good weather. Have fun

                                            2. 1

                                              If you don’t mind sharing, how did you find the place? Are those listed on the airbnb or?

                                              1. 2

                                                You can find rentals on https://www.dansommer.dk/

                                                It seems to combine all the different rental services in their search.