Async Rust: async main

Improving async ergonomics
An 80's style cyberscape with the words "async/.await" printed in the distance. There are a set of glowing eyes in the background and a shadow crab with glowing eyes on the right.

New and improved.

In the previous post we had an introductory glance at async/.await in Rust, looking at what it does and how you'd use it. However, the little bit of code we were left with at the end still felt a bit rough. Coming from languages where you can have an async main function (or at least one that lets you act as if it is), it felt like an extra hurdle to have to extract all async functionality out into a separate function.

Luckily, Reddit user mbuesing pointed out that there is an attribute available in async-std that you can use to make your main function asynchronous: async_std::main! Let's have a look at what changes we'd have to make to incorporate that.

First off, let's update the Cargo.toml file. It's mostly the same as last time, but we're going to have to add the "attributes" feature from async-std:

  name = "async-basics"
  version = "0.1.0"
  authors = ["Your Name <>"]
  edition = "2018"

  async-std = { version = "1", features = ["attributes"] }
  surf = "1"

Next up, let's update the file. If we're doing everything within the main function, we can cut it down to about 8 lines of code, compared to the 14 lines we had last time, and because it's such a simple program, it's not any less readable:

  use surf;

  async fn main() {
      match surf::get("").recv_string().await {
          Ok(s) => println!("Fetched results: {:#?}", s),
          Err(e) => println!("Got an error: {:?}", e),

So there you have it. With some extra attributes, we can make async code pretty ergonomic in Rust. Now, let's make something cool!

Thomas Heartman is a developer, writer, speaker, and one of those odd people who enjoy lifting heavy things and putting them back down again. Preferably with others. Doing his best to gain and share as much knowledge as possible.