use crate

Để sử dụng (import) một crate từ https://crates.io, ví dụ https://crates.io/crates/log.

1. Thêm crate vào Cargo.toml

Có 2 cách

Cách 1: Edit trực tiếp file Cargo.toml

[dependencies]
log = "0.4"

Cách 2: Sử dụng cargo add, cargo sẽ tự động update file Cargo.toml cho bạn

cargo add log
[dependencies]
log = "0.4.17"

Để thêm crate vào dev dependencies (dùng cho tests), ta thêm --dev vào lệnh:

cargo add --dev log
[dev-dependencies]
log = "0.4.17"

2. Sử dụng crate trong code

fn main() {
    log::info!("hello");
    log::error!("oops");
}

Sử dụng keyword use. Chức năng chính của use là bind lại full path của element vào một tên mới, để chúng ta không cần phải lặp lại một tên dài mỗi lần sử dụng.

use log::info;
use log::error;

fn main() {
    info!("hello");
    error!("oops");
}

Nhóm các import lại với nhau:

use log::{info, error};

fn main() {
    info!("hello");
    error!("oops");
}

Import mọi thứ được public trong crate/module. Cách này thường hay tránh bởi sẽ khó biết được function, struct, ... nào đó đang thuộc crate nào, ngoại trừ các prelude::*.

use log::*;

fn main() {
    info!("hello");
    error!("oops");
}

use trong scope

use cũng thường được sử dụng import element vào trong scope hiện tại.

#![allow(unused)]
fn main() {
fn hello() -> String {
  "Hello, world!".to_string()
}

#[cfg(test)]
mod tests {
  use super::hello; // Import the `hello()` function into the scope
    
  #[test]
  fn test_hello() {
    assert_eq!("Hello, world!", hello()); // If not using the above `use` statement, we can run same via `super::hello()`
  }
}
}

Bạn sẽ sẽ hay gặp:

#![allow(unused)]
fn main() {
// ...

#[cfg(test)]
mod tests {
  use super::*;
  use log::info;
    
  // ...
}
}

self::, super::

Mặc định thì use sẽ import đường dẫn tuyệt đối, bắt đầu từ crate root. selfsuper thường dùng để import mod theo vị trí tương đối.

#![allow(unused)]
fn main() {
// src/level_1/level_2/mod.rs

use self::hello_1;
use super::super::level3::hello_2;
}

Re-export

Một trường hợp đặt biệt là sử dụng pub use là re-exporting, khi bạn thiết kế một module bạn có thể export một số thứ từ module khác (*) từ module của bạn. Do đó người sử dụng có thể sử dụng các module khác đó ngay từ module của bạn.

Module khác (*) đó có thể là một internal module, internal crate hoặc external crate.

#![allow(unused)]
fn main() {
// src/utils.rs
pub use log::*;

}
// src/main.rs
use crate::utils::info;

fn main() {
    info!("...");
}

Pattern này được sử dụng khá nhiều ở các thư viện lớn. Nó giúp ẩn đi các internal module phức tạp của library đối với user. Bởi vì user sẽ không cần quan tâm đến cấu trúc directory phức tạp khi sử dụng một library nào đó.