Rustは、高速で信頼性が高く、生産性の高いシステムプログラミング言語です。メモリ安全性とスレッド安全性を保証しながら、高性能なアプリケーションを構築することができます。
Rustをインストールするには、公式サイトからRustupをダウンロードし、指示に従ってインストールします。以下のコマンドで、Rustのバージョンを確認できます:
$ rustc --version
最初のRustプログラムを作成しましょう。以下のコードをmain.rsというファイル名で保存します:
fn main() {
println!("Hello, World!");
}
コンパイルして実行するには:
$ rustc main.rs $ ./main Hello, World!
Rustでは、デフォルトで変数は不変です。可変にするにはmutキーワードを使用します:
let x = 5; // 不変 let mut y = 5; // 可変 y = 6; // OK
Rustは静的型付け言語です。主な型には以下があります:
関数はfnキーワードで定義します:
fn add(x: i32, y: i32) -> i32 {
x + y
}
fn main() {
let result = add(5, 3);
println!("The result is: {}", result);
}
Rustは一般的な制御フロー構文をサポートしています:
// if式
let number = 6;
if number % 2 == 0 {
println!("偶数です");
} else {
println!("奇数です");
}
// ループ
for i in 0..5 {
println!("{}回目", i + 1);
}
// while
let mut n = 0;
while n < 5 {
println!("{}回目", n + 1);
n += 1;
}
Rustの特徴的な概念である所有権は、メモリ管理を安全に行うための仕組みです:
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1の所有権がs2に移動
// println!("{}", s1); // エラー:s1は既に無効
println!("{}", s2); // OK
}
借用(borrowing)は、所有権を移動せずに一時的に値を参照する方法です。
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
可変な借用も可能ですが、同時に1つの可変な借用しか存在できません:
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
列挙型(enum)は、複数の異なる値を持つ可能性がある型を定義します。
enum Result<T, E> {
Ok(T),
Err(E),
}
enum Direction {
North,
South,
East,
West,
}
fn main() {
let result: Result<i32, String> = Result::Ok(42);
let direction = Direction::North;
}
構造体(struct)は、関連するデータをグループ化するためのカスタムデータ型です。
struct Person {
name: String,
age: u32,
}
fn main() {
let person = Person {
name: String::from("Alice"),
age: 30,
};
println!("{} is {} years old.", person.name, person.age);
}
パターンマッチングは、Rustの強力な機能の1つで、データの構造に基づいてコードを分岐させることができます。
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
fn main() {
let coin = Coin::Dime;
println!("The value is {} cents", value_in_cents(coin));
let number = Some(7);
match number {
Some(i) => println!("The value is {}", i),
None => println!("There is no value"),
}
}
Rustは例外を使用せず、Result型とパニックを使用してエラーを処理します。
use std::fs::File;
use std::io::ErrorKind;
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating the file: {:?}", e),
},
other_error => {
panic!("Problem opening the file: {:?}", other_error)
}
},
};
}
?演算子を使用して、エラー処理をより簡潔に書くこともできます:
use std::fs::File;
use std::io;
use std::io::Read;
fn read_username_from_file() -> Result<String, io::Error> {
let mut f = File::open("hello.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
モジュールはコードを整理し、再利用性を高めるのに役立ちます。
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
クレートはRustのコードパッケージです。ライブラリクレートと実行可能クレートの2種類があります。
外部クレートを使用するには、Cargo.tomlファイルに依存関係を追加します:
[dependencies] rand = "0.8.3"
そして、コードで使用します:
use rand::Rng;
fn main() {
let secret_number = rand::thread_rng().gen_range(1..101);
println!("The secret number is: {}", secret_number);
}