Setup
1️⃣ IDE
and tools
- Rust in Visual Studio Code
- Install extra tools.
cargo install cargo-edit # 👈 = cargo add. cargo install cargo-watch # 👈 = cargo watch. cargo install cargo-audit # 👈 = cargo audit.
2️⃣ Use Cargo
💡 📦
Cargo
≈NPM
= Package Manager.
cargo init foo # 👈 Will init app name `foo`.
cargo run # 👈 Build and Run.
cargo watch # 👈 Watch for file change and rebuild.
cargo test # 👈 Test the tests if has.
cargo build --release # 👈 No debug = Smaller/Faster.
cargo add tokio # 👈 add package named `tokio`
cargo rm tokio # 👈 remove package named `tokio`.
💡
tokio
crate makeasync
easier.
3️⃣ Hello World
👩🏻💻 enter
cargo init hello-world
via command line.
📂 hello-world
├─ 📂 src # 👈 keep source code in here.
│ └─ 📄 main.rs # 👈 app entrypoint.
└─ 📦 Cargo.toml
└─ 📄 main.rs
// 👇 main function as an entrypoint. fn main() { // 👇 macro to print something out. println!("hello world!"); // 👈 end with ; suffix. }
└─ 📦 Cargo.toml
[package]
name = "foo" # 👈 App name.
version = "0.1.0" # 👈 App version.
edition = "2021" # 👈 Rust edition.
[dependencies]
tokio = "1.21.2" # 👈 Added by `cargo add tokio`.
⚡️ You can now skip to 👉 enjoy coding or continue reading 4️⃣ below. 👇
4️⃣ Modules and Project structure.
🤔 What if
main.rs
has to many codes? Your should separate that concern to each file/folder.
🗂 App + File Module
Separate some function to each file.
📂 foo
├─ 📂 src
│ ├─ 📄 utils.rs # 👈 module as a file.
│ └─ 📄 main.rs # 👈 will need utils file.
└─ 📦 Cargo.toml
│ ├─ 📄 utils.rs
#![allow(unused)] fn main() { pub fn hello() { // 👈 make it public, or just pub(crate) for internal use. println!("hello world!"); } }
│ └─ 📄 main.rs
mod utils; // 👈 include utils file. use utils; // 👈 and use it. fn main () { utils::hello(); // 👈 call hello function. }
Now you have too many files and want to group it into folder as a module. See below how to👇
🗂 App + Folder Module
Group related files to each folder.
See setup4 example
📂 foo
├─ 📂 src
│ │
│ ├─ 📂 utils
│ │ ├─ 📄 mod.rs # 👈 entrypoint (similar to index.js in JS).
│ │ ├─ 📄 say.rs # 👈 Contain hello function.
│ │ └─ 📄 cast.rs # 👈 will able to use say.
│ │
│ └─ 📄 main.rs # 👈 `mod utils;` then `use utils::say;`
│
└─ 📦 Cargo.toml
│ │ ├─ 📄 mod.rs
#![allow(unused)] fn main() { pub mod say; // 👈 import "say" and export. // 👇 It's look like this in JS. // export * from say; }
│ │ ├─ 📄 say.rs
#![allow(unused)] fn main() { pub fn hello() { // 👈 make it public, or just pub(crate) for internal use. println!("hello world!"); } }
│ │ └─ 📄 cast.rs
#![allow(unused)] fn main() { use super::say // 👈 just use. (no mod need because of super) pub fn cast() { say::hello(); // 👈 then call hello function. } }
│ └─ 📄 main.rs
mod utils; // 👈 include utils file. use utils::say; // 👈 and use. fn main() { say::hello(); // 👈 then call hello function. }
This is better but now you want to reuse that module with other project. Let's make a library then 👇
🗂 Lib
Separate each lib as crate.
cargo init bar --lib
🗂 utils
├─ 📂 src
│ └─ 📄 lib.rs # 👈 lib entrypoint.
└─ 📦 Cargo.toml
│ └─ 📄 lib.rs
#![allow(unused)] fn main() { pub fn hello() { // 👈 make it pub so other can use. println!("hello world!"); } }
🤔 Now you have 3 options to use it.
🗂 Workspace
aka Monorepo.
📂 workspace-example
│
├─ 🗂 utils
│ ├─ 📂 src
│ │ └─ 📄 lib.rs # 👈 lib entrypoint.
│ └─ 📦 Cargo.toml # 1️⃣ utils's cargo.
│
├─ 📂 foo
│ ├─ 📂 src
│ │ └─ 📄 main.rs # 👈 app entrypoint.
│ └─ 📦 Cargo.toml # 2️⃣ foo's cargo.
│
└─ 📦 Cargo.toml # 3️⃣ Workspace's cargo.
│ └─ 📦 Cargo.toml
[dependencies]
foo = { path="../utils" } # 👈 2️⃣ foo's cargo. refer to utils via path
└─ 📦 Cargo.toml
# 👇 3️⃣ Workspace's cargo.
[workspace]
members = [
"utils",
"foo",
]
Next
Let's continue to Enjoy ➠