Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

モジュールシステム

コードを整理する「モジュール」について学びます。

モジュールとは

モジュールはコードを論理的に分割する仕組みです。

my_project/
├── src/
│   ├── main.rs      # エントリーポイント
│   ├── lib.rs       # ライブラリクレートのルート
│   ├── utils.rs     # utilsモジュール
│   └── models/
│       ├── mod.rs   # modelsモジュールのルート
│       └── user.rs  # models::userサブモジュール

基本的なモジュール定義

同一ファイル内

mod greetings {
    pub fn hello() {
        println!("Hello!");
    }

    fn private_function() {
        println!("This is private");
    }
}

fn main() {
    greetings::hello();
    // greetings::private_function();  // エラー!プライベート
}

別ファイルに分割

src/main.rs

mod utils;  // src/utils.rs を読み込む

fn main() {
    utils::greet();
}

src/utils.rs

#![allow(unused)]
fn main() {
pub fn greet() {
    println!("Hello from utils!");
}
}

pub(公開)キーワード

デフォルトはプライベート。pubで公開します。

mod outer {
    pub mod inner {
        pub fn public_function() {
            println!("公開関数");
        }

        fn private_function() {
            println!("非公開関数");
        }
    }
}

fn main() {
    outer::inner::public_function();
}

構造体フィールドの公開

mod models {
    pub struct User {
        pub name: String,    // 公開
        email: String,       // 非公開
    }

    impl User {
        pub fn new(name: String, email: String) -> User {
            User { name, email }
        }

        pub fn email(&self) -> &str {
            &self.email
        }
    }
}

fn main() {
    let user = models::User::new(
        String::from("太郎"),
        String::from("taro@example.com"),
    );
    println!("名前: {}", user.name);
    // println!("メール: {}", user.email);  // エラー!非公開
    println!("メール: {}", user.email());   // メソッド経由でOK
}

use キーワード

長いパスを短縮します。

mod models {
    pub mod user {
        pub struct User {
            pub name: String,
        }
    }
}

// useでパスを短縮
use models::user::User;

fn main() {
    let u = User { name: String::from("太郎") };
    // models::user::User と書かなくてよい
}

複数のインポート

#![allow(unused)]
fn main() {
use std::collections::{HashMap, HashSet};
use std::io::{self, Read, Write};
}

エイリアス(as)

use std::collections::HashMap as Map;

fn main() {
    let mut m: Map<String, i32> = Map::new();
}

再エクスポート(pub use)

#![allow(unused)]
fn main() {
mod models {
    pub mod user {
        pub struct User { pub name: String }
    }
}

// 外部からmodels::Userでアクセス可能にする
pub use models::user::User;
}

ディレクトリ構造

方法1: mod.rs を使う

src/
├── main.rs
└── models/
    ├── mod.rs     # モジュールのルート
    └── user.rs

src/main.rs

#![allow(unused)]
fn main() {
mod models;
use models::User;
}

src/models/mod.rs

#![allow(unused)]
fn main() {
mod user;
pub use user::User;
}

src/models/user.rs

#![allow(unused)]
fn main() {
pub struct User {
    pub name: String,
}
}

方法2: ファイル名でモジュール(Rust 2018以降)

src/
├── main.rs
├── models.rs      # mod models の定義
└── models/
    └── user.rs    # mod models::user の定義

src/models.rs

#![allow(unused)]
fn main() {
pub mod user;
pub use user::User;
}

クレート(Crate)

クレートはRustのコンパイル単位です。

  • バイナリクレート: 実行可能ファイル(main.rs
  • ライブラリクレート: 他のコードから使うライブラリ(lib.rs

外部クレートの使用

Cargo.toml

[dependencies]
rand = "0.8"
serde = { version = "1.0", features = ["derive"] }

src/main.rs

use rand::Rng;

fn main() {
    let n = rand::thread_rng().gen_range(1..100);
    println!("{}", n);
}

実践的なプロジェクト構造

my_app/
├── Cargo.toml
└── src/
    ├── main.rs          # エントリーポイント
    ├── lib.rs           # ライブラリ(オプション)
    ├── config.rs        # 設定モジュール
    ├── error.rs         # エラー定義
    ├── models/
    │   ├── mod.rs
    │   ├── user.rs
    │   └── post.rs
    └── handlers/
        ├── mod.rs
        ├── auth.rs
        └── api.rs

まとめ

概念説明
modモジュールを定義/インポート
pub公開する(デフォルトは非公開)
useパスを短縮
pub use再エクスポート
クレートコンパイル単位(binary/library)

確認テスト

Q1. Rustのアイテム(関数、構造体など)のデフォルトの可視性は?

Q2. use std::collections::{HashMap, HashSet};は何をしている?

Q3. 以下のコードがコンパイルエラーになる理由は?
mod secret { fn hidden() { println!("Hidden!"); } } fn main() { secret::hidden(); }

Q4. pub useの役割は?

Q5. Rustにおける「クレート(Crate)」とは?


次のドキュメント: 06_error_handling_adv.md