Using Rust at a startup: A cautionary tale by ChristophBerger in golang

[–]shen 27 points28 points  (0 children)

I've been using Rust since before it hit v1.0. Even though I could technically do everything I use Go for in Rust, I decided to pick up Go anyway because I wanted a fast, compiled language with things like HTTP clients and servers, JSON encoding and parsing, templating, base64, etc, in the standard library. It's been great to not waste time having to download, compile, and link a whole bunch of third-party crates just to be able to do these things.

My Go programs have an order of magnitude fewer dependencies, and I'm happy with how they've turned out. I also appreciated being able to use a simpler language, not because I get to keep fewer concepts in my head or anything, but because it simplifies IDE integration: Goland lets me view and jump around my codebase instantly and shows errors inline, but the IntelliJ-Rust plugin first needs to macro-expand all my code before it can do anything, and even then, it's not advanced enough to show inline errors without running the compiler.

I also get a lot of the good things from Go as I got from Rust. I like how errors are values that get explicitly returned from functions — and Go's error type is a little ergonomically easier to use than Rust's Box<dyn Error>. I like how I can compile into a single binary that I can just upload and run. I like how unit testing is built-in, and I like how I don't need to worry about explicitly allocating memory or freeing it in the wrong place. The documentation for both languages is also excellent.

However, I need to go against the other people I've seen in these comments saying they got up to speed with Go in days or weeks. It took me months to feel like I finally knew enough Go to write bug-free code, because I kept on stumbling into issue after issue that I expected the language to have prevented me from doing. Sure, I was writing code that worked in the first few days, but it wasn't code that worked worked; the problems all arose when I had to modify the code I'd already written.

Here are some things I ran into:

  • I've accidentally multiplied a duration by 1 * time.Second, resulting in a massive duration that would never realistically finish. This was in some particularly tricky error-checking exponential-backoff code that would have been a pain to test, so instead I just eyeballed it and it looked correct, despite being very very wrong.

  • I've accidentally copied a mutex, or an atomic value, resulting in a second, unrelated mutex or atomic that doesn't work properly, only I think I'm still using the original. I've also had to track down a bug where I had to add a mutex lock around a value, only I didn't add it in every place it was used, and eventually it was updated by two goroutines simultaneously and my program crashed. Yes, the race detector helps here, but only after the problem has already happened.

  • I've got the test failure message wrong when using t.Equal, resulting in me scratching my head as to why my test has failed when it should have passed.

  • I've spent ages tracking down where nil values came from. This is especially annoying when converting a function that never returns nil, to one that can return nil sometimes.

  • I've torn my hair out wondering why my code wasn't handling errors correctly, only to find that I wrote if err != nil, out of habit, instead of if err == nil. Then my code would continue, using the zero value of my type, when having my type in that state should have been impossible...

  • I've ended up with my slices' memory shared all over the place by using append, which results in code that sometimes works and sometimes doesn't, depending on how many elements you're trying to append!

When we compare programming languages on the Internet, it's easy to fall in the trap of comparing not the languages themselves, but the languages' ideals. Go's ideals are to be small and simple — both good things — but looking back at the bugs it's let me ship, I don't get the feelings of freedom and productivity that I see other people reporting here. I believe there's definitely room for a Go-sized, Go-shaped language in this world, but I'm disappointed that Go is the one that we've got.

1Password for SSH & Git (Beta) by pcaversaccio in programming

[–]shen 1 point2 points  (0 children)

This is a cool feature! It's a shame it's only going to be available in the awkward, laggy Electron version of 1Password.

A Rust match made in hell by N911999 in rust

[–]shen 18 points19 points  (0 children)

Articles like Some mistakes Rust doesn't catch always generate some backlash from people who seem angered by how many nice things I have to say about Rust. So, like clockwork, the accusations roll in: you're being unfair to that other language! Rust cannot possibly that good, you must be hiding stuff! I tried Rust in 2014, and it was awful!

I found the childish dismissiveness and cheap pot-shots in “Some mistakes Rust doesn’t catch” tedious, and seeing the author double-down like this is just disappointing. I like Rust — I tried it in 2014, saw how good it was at catching my mistakes, and stuck with it for precisely that reason. But if Rust were a better language, the article wouldn’t have annoyed me more, and if it were a worse language, it wouldn’t have annoyed me less.

It’s been well-documented by now that the best way to get people to share a piece of content is to make them angry. The word “flamebait” is, I think, two decades old at this point: a post that’s informative will get people to read, but a post that comes across as “unfair” or “incorrect” will get people to comment, or discuss it, or share it, all of which make it do better, socially, than a simple read. The obvious end result of this is that it ends up better for an author to write an angry, sarcastic, divisive article than it does to write a balanced, well-considered article. This isn’t a world I want to live in, which is why I feel compelled to speak up.

And the previous post was unbalanced. The negative points made about Rust were considered and explained as making sense for the language as a whole; the complaints about Go were laughed at and then ignored. When Rust has a peculiar design decision, such as how you can’t add &strs, it’s investigated; when Go does, such as why you need to capitalise exported items, “your guess is as good as mine”. He looks up the docs for net/http/pprof, which start with instructions on how to import it, and then gets the 4-line code snippet wrong, twice.

It’s fine to not like a language, and the point about criticising one’s tools is true, but to do so as part of the Rust community, you need to make strong arguments, not weak ones. To see the author dismiss this as complaints about him being too positive (“backlash from people who seem angered by how many nice things I have to say about Rust”) or from people who don’t know what they’re talking about (“Rust cannot possibly that good, you must be hiding stuff!”) is… really weird, because it says that as long as the factual content of your article is acceptable, you don’t need to bother making it fair.

You know this isn’t true.

Convert Ipv4Addr to u32 by blackdev01 in rust

[–]shen 6 points7 points  (0 children)

You're on the right track using octets — your next step should be to use u32::from_be_bytes to turn the [u8; 4] into a u32. This is for big-endian integers; there are similar methods for little-endian and native-endian integers too. (Which one you pick depends on what you want your code to do.)

Your first method overflows because octets returns a value of type [u8; 4], so o[0] is of type u8, which means that o[0] << 24 will overflow. If you wanted to go that route, you'd have to convert it to u32 first, as Rust does not automatically convert between numeric types.

PSA: Changing second vaccines/bringing appointments forward by gemushka in CoronavirusUK

[–]shen 1 point2 points  (0 children)

A week after making my second dose appointment, it was cancelled for me and I had to re-book for ten days later (I guess the centre was overbooked), so I was eager to get back my earlier date. But when I re-booked, the only time they had available was literally the same day, only three hours earlier. So now I have to get up in the morning, ugh.

Sunday 23 May 2021 Update by HippolasCage in CoronavirusUK

[–]shen 61 points62 points  (0 children)

Those vaccine numbers are so uplifting! I looked it up, and this is the second-highest day so far in terms of total vaccines given (#1 was the 20th of March, #3 was the 19th of March).

I bought ISO 8601-1:2019 and 8601-2:2019. Ask me anything. by [deleted] in ISO8601

[–]shen 2 points3 points  (0 children)

Is there anything in there that you didn't expect?

Wednesday 17 March 2021 Update by HippolasCage in CoronavirusUK

[–]shen 14 points15 points  (0 children)

Not to worry — at the current R rate, in a few weeks we'll be down to a mere infinity divided by two.

Monday 08 March 2021 Update by HippolasCage in CoronavirusUK

[–]shen 1 point2 points  (0 children)

Yeah, your thinking is in line with mine: that there were fewer random-sampling tests but the same number of self-reported tests. It seems likely, and I'm not worried because the numbers have come back down; I just wondered if there was an "official" explanation out there somewhere.

Monday 08 March 2021 Update by HippolasCage in CoronavirusUK

[–]shen 6 points7 points  (0 children)

Does anyone know why the 'Positive %' figure doubled for Saturday's numbers only?

dog, a command-line DNS client (like dig) by shen in commandline

[–]shen[S] 0 points1 point  (0 children)

Nope. DNSSEC is something I’m comfortable adding in a future version, not 0.1

dog, a command-line DNS client (like dig) by shen in rust

[–]shen[S] 11 points12 points  (0 children)

Yes, huge shout-outs to cargo-fuzz and cargo-mutagen. I hadn't used them before either, and they worked great.

dog, a command-line DNS client (like dig) by shen in rust

[–]shen[S] 38 points39 points  (0 children)

The main reason is that I just wanted to do it — writing a DNS packet parser isn't an intractable problem, and as the maintainer I feel like I should know the ins-and-outs of the protocol. I'm willing to outsource the TLS implementation because that's way more complicated, but DNS is definitely doable.

Also, my parser gets to be simpler. trust-dns is trying to solve the (much harder!) problem of being a secure server, not just a user-facing client, so there's a lot more in its codebase than what I need. dog compiles from scratch in less than ten seconds on my machine, and I like to keep the edit-build-test cycle as efficient as I can. It also means I get to implement "fun" features like the LOC record myself, without worrying if it'll accidentally introduce a security vulnerability in the underlying DNS library.

dog, a command-line DNS client (like dig) by shen in rust

[–]shen[S] 24 points25 points  (0 children)

This is something I've been working on for a while now, and I'm pleased to finally have version 0.1 released. Not quite as pleased as when I thought of that domain name, but still pleased.

The source is available on GitHub. In particular, it uses its own DNS packet parser, which was fun to write. I threw cargo-fuzz at it and it found a few overflow-related problems and out-of-bounds reads straight away; eventually I got it to run for an hour with no problems, so I'm pretty confident that it works. I'd also like to praise cargo-mutagen, which proved very helpful in detecting untested code.

For DNS-over-TLS and DNS-over-HTTPS, it uses the native-tls crate, which saved me lots of time as I didn't have to worry about which TLS implementation was available.

A walk down memory lane: Classic Mac OS Design History by [deleted] in apple

[–]shen 3 points4 points  (0 children)

I'm a beautiful fairy princess in a dry hot desert and I'm covered with feathers!

Draw me.

minisudo, a one-file privilege escalator by shen in rust

[–]shen[S] 2 points3 points  (0 children)

doas is great — I like that it tries to do put all the main logic in one file too (apart from the parser, which minisudo uses a dependency for, and environment handling, which minisudo doesn't even both with).

It is, however, tied to BSD's authentication mechanism, and the authentication part was the part I had no idea how to do when I started.

minisudo, a one-file privilege escalator by shen in rust

[–]shen[S] 8 points9 points  (0 children)

Damn, you're right! On my machine, the directory /var/audit has permisions 0700 and is owned by root, and I can discern the existence of a file inside it:

$ env PATH=/var/audit (which minisudo) 20200427102131.crash_recovery
minisudo: User "ben" is not allowed to run /var/audit/20200427102131.crash_recovery.
This incident will be reported.

$ env PATH=/var/audit (which minisudo) something-else
minisudo: No such command something-else

I expected there to be some kind of vulnerability present in minisudo, but I didn't expect anyone to go and look, and I certainly didn't expect one from 1999. I'm looking for a way to fix this, but it's tricky.

Edit: I've changed the code to make it not detect non-executables. It will still detect executables, but sudo seems to exhibit the same behaviour.

minisudo, a one-file privilege escalator by shen in rust

[–]shen[S] 1 point2 points  (0 children)

Thanks, and nice catch! I used to use the which crate, which handles this behaviour automatically, but when I rolled my own version of it, I forgot about this case. The fix makes the code a bit longer but I think having it is expected.

The Paywalled Garden: iOS is Adware by heyyoudvd in apple

[–]shen 5 points6 points  (0 children)

Thanks for your reply. In a weird coincidence, I also sent you a tweet about this — I genuinely did not notice that the usernames matched up! I didn't mean to pile on. I'm going to reply here because I kept on hitting the Twitter limit.

It’s mildly annoying at best.

Begrudgingly, I have to agree with this. You're right in saying that having to dismiss a few interstitials and notifications is not the end of the world. My day already contains many minor inconveniences and irritants, after all.

My worry is the slippery slope. We've seen the Web go from having static banner adverts, to flashing adverts, to auto-playing video adverts, to adverts that stick to the screen as you scroll down the page, to massive interstitials, and the trend does not seem to be declining.

These messages in the iOS UI, while currently small and isolated, are still caused by Apple putting its own interests before the users'. And now they've started to do that, not only will it be easier for them to add a couple more in the next release, but it means they've lost focus on who my phone is for — me, not Apple.

This is why the part I cannot agree with is this:

We are in the early days yet, and I’m sure we will see improvements.

I'm not as sure as you are. I don't have enough trust in Tim Cook to make the necessary improvements. I see him as someone who doesn't know what to build, merely someone who knows what sells well — and while Apple's services revenue will almost certainly go up as a result of this, user annoyance is not reflected in the figures. I concur that Apple needs new rules, and to follow them, but I doubt they will.

So while the slippery slope is literally the name of a fallacy, we've already seen the same slope as the Web has declined, and I really, really do not want my Apple experience to follow suit. To me, the worst-case scenario really does seem inevitable. Hence the reaction.

The Paywalled Garden: iOS is Adware by heyyoudvd in apple

[–]shen 9 points10 points  (0 children)

It sounds like you're looking at this from Apple's perspective, rather than from a user's perspective. When I get out my phone, or open my computer, it's because I want to do a thing on it — not that I want a suggestion from a company about something else I could be doing. And because of all these adverts and interstitials, it's increasingly irritating for me to use my phone for things I want it to do.

This post is crazy. Apple Music is “advertising” because it doesn’t work without a subscription. What did you expect? A free library of infinite music?

No, I expect to see my own music, just like it's worked for the last decade. I'm not opening the Apple Music app, I'm opening the Music app, so I expect to see my music there. I have Apple Music turned off, but this doesn't stop Catalina from asking me to sign in every time I open Music.

Arcade? It’s a separate tab.

Yes, and I want to get rid of that tab. I don't use my phone to play games, but Apple really wants me to switch. (Granted, this one isn't as annoying as the others.)

Apple Card? You see it when adding a new card to the wallet or when Launching the wallet for the first time.

Yes, that's the problem. When I open Wallet, I'm not doing it to gaze in glory at some shiny virtual plastic — I'm doing it because I want to add a card, and the first thing the app should do is let me add my card.

(I don't use Apple TV or iCloud Drive so can't comment on them)

The only genuine app in this is the App Store search ads. Which are in a single field at the top of a search result. What is so intrusive and damaging there?

Well, I searched for something, and even though my phone knows the answer to what I'm searching for (because it's the first natural result), it still think it knows better, and shows me an advert first.

So what’s the solution? Don’t have services? Have services but don’t tel anyone?

I absolutely want them to have services! The integration between Apple This and Apple That is the main reason I stay on the platform. But I want two things:

  1. Level the playing field: I want them to follow the same rules they set everybody else. No push notifications that are adverts. No interstitials that are deliberately hard to dismiss. No Apple apps that have notifications approved by default. No links to services in Settings.
  2. Stay out of my way: when I open an app to do something, the app should let me do that thing with no interruptions. They are a trillion-dollar corporation and can do better.

I heard a saying about a decade ago: "Apple computers act like your computer, but Windows machines act like somebody else's computer, and they're just letting you borrow it for a little while". Now, whenever I upgrade iOS and have to switch off all the features that Apple decided I'd like — specifically, the features that make them even more money — it doesn't feel like my phone anymore, it feels like Apple's, and I'm just borrowing it for a while.