コンテンツにスキップ

V/イディオム

出典: フリー教科書『ウィキブックス(Wikibooks)』
< V

値の初期化

[編集]

構造体の初期化

[編集]

Vでは構造体の初期化に短縮記法が用意されています。フィールド名と変数名が同じ場合、値の指定を省略できます。

struct User {
    name string
    age  int
}

// 通常の初期化
name := 'Alice'
user1 := User{
    name: name
    age: 25
}

// 短縮記法を使用
name := 'Alice'
user2 := User{
    name    // nameフィールドにname変数の値が設定される
    age: 25
}

デフォルト値の設定

[編集]

構造体フィールドのデフォルト値は構造体定義時に指定します。

struct Configuration {
    timeout int = 30    // デフォルト値30
    host    string = 'localhost'
    port    int = 8080
}

// デフォルト値を使用
config := Configuration{}
assert config.timeout == 30

エラー処理

[編集]

エラーの伝播

[編集]

エラーを上位に伝播させる場合は!を使用します。これにより、エラーハンドリングの意図が明確になります。

fn read_config() !string {
    // os.read_file()は!stringを返す
    content := os.read_file('config.txt')!
    return content
}

fn initialize() ! {
    config := read_config()!  // エラーを伝播
    // 設定を使用した処理
}

エラーの変換

[編集]

or節でエラーを別の型に変換できます。これは、より具体的なエラー情報を提供したい場合に便利です。

fn connect_to_database(url string) !Database {
    db := sql.connect(url) or {
        return error('データベース接続エラー: ${err}')
    }
    return db
}

コレクション操作

[編集]

配列の変換

[編集]

配列の要素を変換する場合、mapメソッドを使用します。

numbers := [1, 2, 3, 4, 5]
// 各要素を2倍
doubled := numbers.map(it * 2)
// 文字列に変換
strings := numbers.map(it.str())

フィルタリング

[編集]

条件に合う要素のみを抽出する場合、filterメソッドを使用します。

numbers := [1, 2, 3, 4, 5]
// 偶数のみ抽出
even := numbers.filter(it % 2 == 0)
// 特定の条件で抽出
large := numbers.filter(it > 3)

並行処理

[編集]

複数の処理の待ち合わせ

[編集]

複数のgoroutineの完了を待つ場合、結果を配列で受け取ります。

fn process(id int) int {
    time.sleep(100 * time.millisecond)
    return id * 2
}

fn main() {
    mut handles := []thread int{}
    // 複数の処理を開始
    for i in 0..3 {
        handles << go process(i)
    }
    // すべての結果を待機
    results := handles.wait()
    println(results)  // [0, 2, 4]
}

チャネルを使用したパイプライン

[編集]

チャネルを使用して、データの流れを表現できます。

fn generator(ch chan int) {
    for i in 0..5 {
        ch <- i
    }
    ch.close()
}

fn square(in chan int, out chan int) {
    for num in in {
        out <- num * num
    }
    out.close()
}

fn main() {
    ch1 := chan int{}
    ch2 := chan int{}
    go generator(ch1)
    go square(ch1, ch2)
    // 結果を受信
    for squared in ch2 {
        println(squared)
    }
}

リソース管理

[編集]

自動クローズ

[編集]

リソースの解放が必要な処理は、defer節で記述します。

fn process_file() ! {
    mut file := os.open('data.txt')!
    defer {
        file.close()
    }
    // ファイル処理
}

スコープを利用したリソース管理

[編集]

一時的なリソースはブロックスコープで管理します。

fn process_data() ! {
    {
        mut temp_file := os.open('temp.txt')!
        defer {
            temp_file.close()
            os.rm('temp.txt') or {}
        }
        // 一時ファイルを使用した処理
    } // ここでファイルが閉じられ、削除される
    
    // 後続の処理
}

型の活用

[編集]

ジェネリック関数での型制約

[編集]

ジェネリック関数で型パラメータに制約を設定できます。

// 数値型のみを受け付ける
fn sum[arr []T T > int || f64] T {
    mut total := T(0)
    for num in arr {
        total += num
    }
    return total
}

// インターフェースを実装する型のみを受け付ける
interface Stringable {
    to_string() string
}

fn print_values[items []T T > Stringable] {
    for item in items {
        println(item.to_string())
    }
}

Option型の活用

[編集]

値が存在しない可能性がある場合は、Option型を使用します。

struct User {
    name string
    bio  ?string  // バイオグラフィーは省略可能
}

fn get_bio(user User) string {
    return user.bio or {
        'バイオグラフィーはまだ設定されていません'
    }
}

テスト

[編集]

テストの構造化

[編集]

テストは機能単位でグループ化します。

fn test_user_creation() {
    user := User{
        name: 'test'
        age: 20
    }
    assert user.name == 'test'
    assert user.age == 20
}

fn test_user_validation() {
    user := User{
        name: ''
        age: -1
    }
    assert !is_valid_user(user)
}

テストヘルパー

[編集]

よく使用するテスト用の補助関数は、別モジュールにまとめます。

module test_helpers

pub fn create_test_user() User {
    return User{
        name: 'test_user'
        age: 20
    }
}

pub fn setup_test_db() !Database {
    db := Database{
        path: ':memory:'
    }
    return db
}