24の最小限の例で学ぶRustの基礎
Takashi Yamamoto
Infrastructure Engineer · Leapcell

Rustは、安全性、パフォーマンス、並行性に優れ、豊かでユニークな言語構造を持つシステムプログラミング言語として知られています。この記事では、Rustの核となる機能を24の簡潔なコード例を通して紹介します。
パターンマッチング
Rustのmatch
式はパターンマッチングを実装し、値が一連のパターンに適合するかどうかを確認できます。
let number = Some(42); match number { Some(x) => println!("The number is {}", x), None => println!("There is no number"), }
このコードは、Option
型のさまざまなケースを処理するためにmatch
式をどのように使用するかを示しています。
所有権とライフタイム
ライフタイムパラメータを使用することで、Rustは参照が有効なままであり、ダングリングポインタを回避することを保証します。
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }
この関数は、2つの文字列スライスを受け取り、より長い方を返します。ライフタイム'a
は、返される参照が有効であることを保証します。
ジェネリクス
ジェネリクスを使用すると、正確な型を指定せずに関数と構造体を定義できます。
fn largest<T: PartialOrd + Copy>(list: &[T]) -> T { list.iter().cloned().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap() }
このジェネリック関数largest
は、PartialOrd
およびCopy
トレイトを実装する任意の型のリストから最大値を検索します。
トレイト
トレイトはインターフェースに似ており、実装できるメソッドのセットを定義します。
trait Summary { fn summarize(&self) -> String; }
Summary
トレイトは、オブジェクトのテキストによる要約を提供するために、任意の型によって実装できます。
型キャスト
Rustは、型変換を実行するためのいくつかの方法を提供します。
let decimal: f64 = 6.0; let integer: i32 = decimal as i32; // 明示的な型変換
このコードは、f64
型の値をi32
に明示的に変換する方法を示しています。
エラー処理
Rustは、潜在的なエラーを処理するためにResult
型を使用します。
fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err("Cannot divide by zero".to_string()) } else { Ok(a / b) } }
このdivide
関数は、除数がゼロの場合にエラーを返します。
イテレータ
イテレータは、Rustにおけるシーケンスを処理するための強力な抽象化です。
let a = [1, 2, 3]; let mut iter = a.iter(); while let Some(&item) = iter.next() { println!("{}", item); }
このコードは、イテレータを使用して配列をトラバースします。
クロージャ
クロージャは、Rustの匿名関数です。
let list = vec![1, 2, 3]; let even_numbers: Vec<i32> = list.into_iter().filter(|&x| x % 2 == 0).collect();
ここでは、クロージャを使用してVec
から偶数を除外します。
Asyncプログラミング
非同期コードを使用すると、プログラムはI/O操作を待機している間に他のタスクを実行できます。
async fn fetch_data() -> Result<(), Error> { // Code to fetch data asynchronously Ok(()) }
このfetch_data
関数は非同期であり、非同期ランタイム内で呼び出すことができます。
スマートポインタ
スマートポインタは、追加の機能と動的な動作を備えたポインタです。
use std::rc::Rc; let a = Rc::new(5); let b = Rc::clone(&a);
ここで、Rc<T>
は参照カウントされたスマートポインタであり、同じデータの複数の所有者を許可します。
スレッド
Rustのstd::thread
モジュールは、スレッドを作成および管理する機能を提供します。
use std::thread; let handle = thread::spawn(|| { println!("Hello from a thread!"); }); handle.join().unwrap();
このコードは新しいスレッドを生成し、その中でメッセージを出力します。
チャネル
チャネルは、Rustにおけるスレッド間の通信のためのメカニズムです。
use std::sync::mpsc; let (tx, rx) = mpsc::channel(); tx.send("Hello").unwrap(); let message = rx.recv().unwrap();
ここでは、スレッド間でメッセージを渡すためのチャネルが作成されます。
アトミック型
アトミック型は、スレッドセーフな共有状態を提供します。
use std::sync::atomic::{AtomicUsize, Ordering}; let count = AtomicUsize::new(0);
AtomicUsize
は、マルチスレッドコンテキストで安全に使用できる符号なし整数です。
条件付きコンパイル
条件付きコンパイルを使用すると、プラットフォームまたは構成に応じて異なるコードをコンパイルできます。
#[cfg(target_os = "windows")] fn is_windows() -> bool { true }
この属性マクロは、ターゲットオペレーティングシステムがWindowsの場合にのみis_windows
関数を有効にします。
マクロ
マクロは、Rustの強力な機能であり、コードを生成できます。
#[macro_use] extern crate serde_derive;
ここで、serde_derive
マクロは、シリアル化およびデシリアル化コードの記述を簡素化します。
モジュールとパッケージ
モジュールシステムを使用すると、コードを階層構造に整理できます。
mod my_module { pub fn do_something() { // ... } }
my_module
は現在のファイル内のモジュールであり、外部からアクセスできる関数do_something
が含まれています。
フィーチャーゲート
フィーチャーゲートは、特定の機能が誤用されるのを防ぐための方法です。
#![feature(untagged_unions)]
この属性マクロは、Rustでまだ安定していない実験的なuntagged_unions
機能を有効にします。
メモリ割り当て
Rustでは、メモリアロケータのカスタマイズが可能です。
use std::alloc::{GlobalAlloc, Layout}; struct MyAllocator; unsafe impl GlobalAlloc for MyAllocator { unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { // ... } }
ここでは、カスタムグローバルアロケータMyAllocator
が定義されています。
生ポインタ
生ポインタは、低レベルのメモリ制御を提供します。
let mut v = vec![1, 2, 3]; let ptr: *mut i32 = v.as_mut_ptr();
このコードは、Vec
への生ポインタを取得し、その内部の整数を直接操作できるようにします。
共用体
共用体を使用すると、さまざまなデータ型がメモリを共有できます。
union MyUnion { i: i32, f: f32, }
MyUnion
は、i32
またはf32
のいずれかを格納できますが、一度に1つだけです。
列挙型
Rustの列挙型は、いくつかのバリアントのいずれかになる可能性のある型を表すために使用されます。
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), }
Message
列挙型は、Quit
、座標を持つMove
、または文字列を含むWrite
にすることができます。
構造分解
構造分解を使用すると、構造体またはタプルから値を抽出できます。
let (x, y, z) = (1, 2, 3);
これは、タプルを構造分解して、3つの変数を同時に作成します。
ライフタイムエリジョン
Rustのコンパイラは、特定の場合にライフタイムを自動的に推論できます。
fn borrow<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { if *x > *y { x } else { y } }
この関数では、コンパイラはライフタイムパラメータを自動的に推論できます。
インラインアセンブリ
インラインアセンブリを使用すると、アセンブリ命令をRustコードに埋め込むことができます。
// Requires specific architecture and environment setup unsafe { asm!("nop", options(nomem, nostack)); }
このコードは、asm!
マクロを使用してnop
(no operation)命令を挿入します。
Rustプロジェクトのホスティングには、Leapcellをご利用ください。
Leapcellは、Webホスティング、非同期タスク、Redisのための次世代サーバーレスプラットフォームです:
多言語サポート
- Node.js、Python、Go、またはRustで開発。
無制限のプロジェクトを無料でデプロイ
- 使用量のみを支払い - リクエストも料金もなし。
比類のないコスト効率
- アイドル料金なしの従量課金制。
- 例:$25で平均応答時間60msで694万リクエストをサポート。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的なUI。
- 完全に自動化されたCI/CDパイプラインとGitOps統合。
- 実用的な洞察のためのリアルタイムメトリクスとロギング。
容易なスケーラビリティと高性能
- 高い並行性を容易に処理するための自動スケーリング。
- 運用上のオーバーヘッドはゼロ - 構築に集中するだけです。
詳細については、ドキュメントをご覧ください!
Xでフォローしてください: @LeapcellHQ