Rust入門:基本的な概念と機能の解説
Rust入門:基本的な概念と機能の解説
Rustは安全性、パフォーマンス、並行性に優れたシステムプログラミング言語です。この記事では、Rustの重要な基本概念について説明します。初心者の方からRustに興味を持った方まで、参考になれば幸いです。
目次
- Cargoの
--features
オプション - 構造体とアクセス修飾子
impl
ブロックによるメソッド実装Result
型とunwrap
- エラーハンドリングの改善
- アトリビュートと条件付きコンパイル
- モジュールシステムとインポート
Cargoの--features
オプション
基本概念
Cargoの--features
オプションは、Rustのパッケージ(クレート)で定義された条件付き機能を有効にするための仕組みです。フィーチャーとは、クレートの「オプショナルな機能」を表します。これにより、ユーザーは必要な機能だけを選択的に有効化できるため、不要な依存関係をインクルードせずに済み、コンパイル時間の短縮やバイナリサイズの削減が可能になります。
使用方法
|
|
または複数のフィーチャーをカンマ区切りで指定することもできます:
|
|
Cargo.tomlでの定義方法
クレート作者はCargo.toml
ファイルでフィーチャーを以下のように定義します:
|
|
full
フィーチャー
多くのRustクレートでは、full
という名前のフィーチャーが「すべての機能を有効にする」ためのショートカットとして提供されています。
|
|
使用例:
|
|
デフォルトの動作
--features
を指定しない場合、Cargo.toml
ファイルの[features]
セクションでdefault
として指定された機能だけが有効になります。デフォルト機能も含めて何も有効にしたくない場合は、--no-default-features
フラグを使用できます。
構造体とアクセス修飾子
Rustには構造体(struct)という機能があり、関連するデータをグループ化するために使用されます。
基本的な構造体の定義
|
|
Rustのアクセス修飾子(可視性)
Rustには伝統的なpublic
/private
/protected
という名前のアクセス修飾子はありませんが、代わりに以下の可視性制御機能があります:
- pub - 公開(public)。他のモジュールからアクセス可能
- デフォルト - 非公開(private)。同じモジュール内からのみアクセス可能
例:
|
|
詳細な可視性制御
より細かい制御のために、Rustには以下の可視性修飾子もあります:
- pub(crate) - クレート内でのみ公開
- pub(super) - 親モジュールにのみ公開
- pub(in path) - 指定したパスにのみ公開
|
|
impl
ブロック
Rustでは構造体にメソッドを追加するためにimpl
キーワード(implementation「実装」の略)を使用します。
基本的なimplの使い方
|
|
implブロックの特徴
-
複数のimplブロック: 同じ構造体に対して複数の
impl
ブロックを定義できます。 -
ジェネリック構造体への実装:
1 2 3 4 5 6 7 8 9 10
struct Point<T> { x: T, y: T, } impl<T> Point<T> { fn get_x(&self) -> &T { &self.x } }
-
トレイトの実装にも使用:
1 2 3 4 5
impl Display for Rectangle { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "Rectangle({}x{})", self.width, self.height) } }
Result
型とunwrap
Result
型の基本
Result<T, E>
はRustのエラー処理のための標準的な列挙型で、次のように定義されています:
|
|
この型は、失敗する可能性のある操作の結果を表現するために使用されます。例えば、ファイル操作やネットワーク通信などです。
unwrap
メソッドの説明
unwrap
はResult
型に対して以下の動作を行うメソッドです:
|
|
動作メカニズム
Result
がOk(value)
の場合:内部の値value
を取り出して返しますResult
がErr(e)
の場合:プログラムがパニックを起こし、実行を中断します
unwrap
の危険性
unwrap
は便利ですが、以下の理由から本番コードでは注意が必要です:
- エラーが発生するとプログラムが強制終了する
- カスタムエラーメッセージがなく、デバッグが難しい場合がある
- エラー処理の機会を逃してしまう
エラーハンドリングの改善
unwrap()
を避けるためのより良い方法を紹介します。以下はAxumベースのウェブサーバーの例です:
1. ?
演算子を使用する
|
|
2. より詳細なエラーハンドリング
エラーの理由に基づいて異なる処理を行う場合:
|
|
3. expect()
の使用
少なくともunwrap()
よりは情報量の多いパニックメッセージを提供できます:
|
|
その他の便利なメソッド
unwrap_or(default)
: エラーの場合にデフォルト値を返すunwrap_or_else(|err| ...)
: エラーの場合にクロージャを実行map_err(|err| ...)
: エラー型を変換
アトリビュートと条件付きコンパイル
アトリビュート
Rustの #[]
はアトリビュート(attribute)と呼ばれています。アトリビュートはRustのコードに付加的な情報やメタデータを提供するための機能で、コンパイラへの指示やコード生成のヒントを与えるために使用されます。
代表的なアトリビュートの例:
#[derive(Debug, Clone)]
- 自動的にトレイト実装を生成#[cfg(test)]
- 条件付きコンパイル(testビルド時のみコンパイル)#[allow(dead_code)]
- 特定の警告を抑制#[tokio::main]
- 非同期ランタイムのエントリーポイントを定義
cfg
アトリビュート
#[cfg]
アトリビュートは「Configuration(設定)」の略で、条件付きコンパイルを実現するための機能です。特定の条件が満たされた場合にのみ、コードの一部をコンパイルすることができます。
|
|
複合条件
論理演算子を使用した複雑な条件:
|
|
モジュールシステムとインポート
use super::*;
の意味
use super::*;
は、Rustのモジュールシステムにおける「親モジュールからすべての公開アイテムをインポートする」という命令です。
use
- 他の場所で定義されたものを現在のスコープに持ち込むsuper
- 親モジュール(現在のモジュールの上位モジュール)を指す::
- パス区切り文字*
- ワイルドカード(すべての公開アイテムを意味する)
実際の例
|
|
Rustのモジュールパス参照キーワード
Rustのモジュールシステムでは、相対パスを指定するために以下のキーワードが使われます:
self
- 現在のモジュール自身super
- 親モジュール(一つ上のレベル)crate
- 現在のクレートのルート
推奨されるインポートスタイル
本番コードでは、名前の衝突を避けるため、*
によるワイルドカードインポートは控え、必要なアイテムを個別に指定することが推奨されています:
|
|
まとめ
この記事では、Rustの基本的な概念について解説しました。Rustの特徴的な機能であるフィーチャーフラグ、構造体とその可視性制御、impl
ブロックでのメソッド実装、エラーハンドリングのパターン、アトリビュートによる条件付きコンパイル、そしてモジュールシステムについて学びました。
Rustは最初は学習曲線が急かもしれませんが、これらの概念を理解することで、安全で効率的なコードを書くことができるようになります。さらに深く学ぶためには、The Rust Programming Language(通称「The Book」)を読むことをお勧めします。