Go言語入門:ランダム処理

スポンサーリンク
Go言語入門:ランダム処理 未分類
Go言語入門:ランダム処理
この記事は約11分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、Golangでのランダム処理についてご紹介します。

スポンサーリンク

前提条件

前回の記事では、エラー処理についてご紹介しました。

今回の記事では、あらかじめ定義されたいくつかのメッセージ形式の中からランダムに1つのメッセージ形式を適用してメッセージを返すようにコードを変更することにします。

そのため、下記の記事が実行できる環境にあることを前提にしています。

利用方法

作業ディレクトリを作成して、移動する。

mkdir 08_learn-golang-handle-random
cd 08_learn-golang-handle-random

asdfコマンドで使用するGolangのバージョンを指定します。

すでにGolangが実行できる状態にある方は、このコマンドをスキップしても問題ありません。

asdf local golang 1.20.5

前回の記事のソースコードを作業ディレクトリにコピーします。

cp -r ../07_learn-golang-handle-errors/greetings .
cp -r ../07_learn-golang-handle-errors/hello .    

以下のコードをgreetings.goファイルに貼り付け、ファイルを保存してください。

package greetings

import (
    "errors"
    "fmt"
    "math/rand"
)

// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
    // If no name was given, return an error with a message.
    if name == "" {
        return name, errors.New("empty name")
    }
    // Create a message using a random format.
    message := fmt.Sprintf(randomFormat(), name)
    return message, nil
}

// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
    // A slice of message formats.
    formats := []string{
        "Hi, %v. Welcome!",
        "Great to see you, %v!",
        "Hail, %v! Well met!",
    }

    // Return a randomly selected message format by specifying
    // a random index for the slice of formats.
    return formats[rand.Intn(len(formats))]
}

以下のコードをhello.goファイルに貼り付け、ファイルを保存してください。

前回との差分は、greetings.Helloに渡す文字列が、空文字から”Gladys”に変わった点です。

package main

import (
    "fmt"
    "log"

    "example.com/greetings"
)

func main() {
    // Set properties of the predefined Logger, including
    // the log entry prefix and a flag to disable printing
    // the time, source file, and line number.
    log.SetPrefix("greetings: ")
    log.SetFlags(0)

    // Request a greeting message.
    message, err := greetings.Hello("Gladys")
    // If an error was returned, print it to the console and
    // exit the program.
    if err != nil {
        log.Fatal(err)
    }

    // If no error was returned, print the returned message
    // to the console.
    fmt.Println(message)
}

helloディレクトリに移動して、hello.goを実行し、コードが動作することを確認します。

cd hello 
go run .

複数回実行し、下記のようにメッセージが変化することが確認できればOKです。

% go run .
Hail, Gladys! Well met!

% go run .
Great to see you, Gladys!

% go run .
Hi, Gladys. Welcome!

解説

greetings.go

package greetings

import (
    "errors"
    "fmt"
    "math/rand"
)

// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
    // If no name was given, return an error with a message.
    if name == "" {
        return name, errors.New("empty name")
    }
    // Create a message using a random format.
    message := fmt.Sprintf(randomFormat(), name)
    return message, nil
}

// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
    // A slice of message formats.
    formats := []string{
        "Hi, %v. Welcome!",
        "Great to see you, %v!",
        "Hail, %v! Well met!",
    }

    // Return a randomly selected message format by specifying
    // a random index for the slice of formats.
    return formats[rand.Intn(len(formats))]
}

このコードは、greetingsというパッケージ内に定義された関数とメソッドを含んでいます。以下にコードの説明を示します。

  1. importステートメント: errorsfmtmath/randという3つのパッケージをインポートしています。
  2. Hello関数: nameという文字列を引数として受け取ります。関数は文字列とエラーを返します。処理の概要は以下の通りです。
    • nameが空の場合、エラーを返します(errors.New("empty name"))。
    • ランダムなフォーマットを使ってメッセージを作成します。
    • フォーマット文字列にnameを埋め込んでメッセージを生成し、それを返します。
  3. randomFormat関数: ランダムに選択された挨拶メッセージを返します。以下の手順で処理が行われます。
    • formatsという文字列のsliceに複数のフォーマットが定義されています。
    • rand.Intn(len(formats))を使ってformats sliceの中からランダムにインデックスを選択し、そのインデックスに対応するメッセージフォーマットを返します。

このコードは、Hello関数を呼び出すことで指定した名前に対してランダムな挨拶メッセージを生成することができます。nameが空の場合はエラーが返されます。また、randomFormat関数は複数のメッセージフォーマットからランダムに選択されたメッセージを返します。

sliceについて

今回の記事ではGolangのsliceを使っています。sliceは配列のようなものですが、項目を追加したり削除したりするとサイズが動的に変化します。sliceは、Golangの最も便利な型の1つです。

ここでは、3つの挨拶メッセージを格納する小さなsliceを追加し、コードがそのうちの1つをランダムに返すようにします。

Go言語では、スライス(slices)は配列に対するより柔軟なデータ構造です。スライスは可変長であり、要素の追加や削除が容易です。以下にスライスについての詳細を説明します。

  1. スライスの作成: スライスは、既存の配列や他のスライスから作成することができます。以下はスライスの作成方法の例です。
// 配列からスライスを作成
array := [4]int{1, 2, 3, 4}
slice := array[1:3] // [2, 3]

// スライスからスライスを作成
originalSlice := []int{1, 2, 3, 4, 5}
newSlice := originalSlice[2:4] // [3, 4]
  1. スライスの要素へのアクセス: スライスは0から始まるインデックスを使用して要素にアクセスします。インデックスを指定することで、特定の要素にアクセスしたり、スライスの一部を取得したりすることができます。
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice[0])   // 1
fmt.Println(slice[2:4]) // [3, 4]
  1. スライスの要素の追加と削除: スライスには組み込みのappend関数を使用して要素を追加することができます。append関数は元のスライスを変更せずに、新しいスライスを返します。
slice := []int{1, 2, 3}
slice = append(slice, 4) // [1, 2, 3, 4]

スライスから要素を削除するには、インデックスを指定してappend関数を使用することで実現できます。

slice := []int{1, 2, 3, 4}
slice = append(slice[:2], slice[3:]...) // [1, 2, 4]
  1. スライスの長さと容量: スライスはlen関数を使用して現在の要素数を取得できます。また、cap関数を使用してスライスの容量(内部配列のサイズ)を取得できます。スライスの容量は、元の配列の先頭から数えた要素数です。
slice := []int{1, 2, 3, 4, 5}
fmt.Println(len(slice)) // 5
fmt.Println(cap(slice)) // 5

  1. スライスのコピー: copy関数を使用すると、スライスの要素を別のスライスにコピーすることができます。
slice1 := []int{1, 2, 3}
slice2 := make([]int, len(slice1))
copy(slice2, slice1)

  1. スライスの結合: append関数を使用して、2つ以上のスライスを結合することができます。
slice1 := []int{1, 2}
slice2 := []int{3, 4}
slice3 := append(slice1, slice2...) // [1, 2, 3, 4]
  1. スライスのイテレーション: forループを使用してスライスの要素に順番にアクセスすることができます。
slice := []string{"apple", "banana", "cherry"}
for index, value := range slice {
    fmt.Println(index, value)
}

  1. スライスのゼロ値: スライスは参照型であり、ゼロ値はnilです。ゼロ値のスライスは要素数0で、メモリ上には割り当てられません。
var slice []int // nilスライス
fmt.Println(slice == nil) // true
fmt.Println(len(slice))   // 0

スライスはGo言語の重要なデータ構造であり、動的な要素の管理や操作に便利です。スライスは配列の上に抽象化されたレイヤーを提供し、より柔軟なデータ操作を可能にします。

sliceについて詳しくは、GoブログのGoスライスを参照してください。

おわりに

今日は、Golangでランダム処理する方法についてご紹介しました。

本記事で使用したコードは下記のリポジトリにあります。

よっしー
よっしー

何か質問や相談があれば、遠慮なくコメントしてください。また、エンジニア案件についても、いつでも相談にのっていますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました