序章

条件付きステートメントを使用すると、プログラマーは、条件が真の場合は何らかのアクションを実行し、条件が偽の場合は別のアクションを実行するようにプログラムに指示できます。 多くの場合、いくつかの変数を複数の可能な値と比較し、状況ごとに異なるアクションを実行します。 ifステートメントのみを使用してこの作業を行うことができます。 ただし、ソフトウェアを作成することは、物事を機能させるだけでなく、将来の自分や他の開発者にあなたの意図を伝えることでもあります。 switch は、さまざまなオプションが提示されたときにGoプログラムによって実行されるアクションを伝達するのに役立つ代替の条件ステートメントです。

switchステートメントで記述できるものはすべて次のように記述できます。 if ステートメント。 このチュートリアルでは、switchステートメントで実行できることのいくつかの例を見ていきます。 if それが置き換えるステートメント、およびそれが最も適切に適用される場所。

Switchステートメントの構造

スイッチは通常、変数に特定の値が割り当てられたときにプログラムによって実行されるアクションを説明するために使用されます。 次の例は、これを使用してこれを実現する方法を示しています if ステートメント:

package main

import "fmt"

func main() {
	flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}

	for _, flav := range flavors {
		if flav == "strawberry" {
			fmt.Println(flav, "is my favorite!")
			continue
		}

		if flav == "vanilla" {
			fmt.Println(flav, "is great!")
			continue
		}

		if flav == "chocolate" {
			fmt.Println(flav, "is great!")
			continue
		}

		fmt.Println("I've never tried", flav, "before")
	}
}

これにより、次の出力が生成されます。

Output
chocolate is great! vanilla is great! strawberry is my favorite! I've never tried banana before

内部 main、アイスクリームフレーバーのスライスを定義します。 次に、forループを使用してそれらを反復処理します。 3つ使用します if さまざまなアイスクリームフレーバーの好みを示すさまざまなメッセージを印刷するステートメント。 各 if ステートメントは使用する必要があります continue の実行を停止するステートメント for ループして、最後のデフォルトのメッセージが好みのアイスクリームフレーバーに対して印刷されないようにします。

新しいアイスクリームの好みを追加するとき、追加し続ける必要があります if 新しいケースを処理するステートメント。 の場合のように、重複したメッセージ "vanilla""chocolate"、重複している必要があります if ステートメント。 私たちのコードの将来の読者(私たち自身を含む)にとって、 if ステートメントは、変数を複数の値と比較し、さまざまなアクションを実行するという、実行していることの重要な部分をあいまいにします。 また、フォールバックメッセージは条件とは別に設定されているため、無関係に見えます。 The switch ステートメントは、このロジックをより適切に整理するのに役立ちます。

The switch ステートメントはで始まります switch キーワードであり、最も基本的な形式で、比較を実行するための変数が続きます。 この後に中括弧のペアが続きます({})複数のcase句を表示できます。 case句は、switchステートメントに提供された変数がcase句によって参照される値と等しい場合にGoプログラムが実行する必要のあるアクションを記述します。 次の例では、前の例を変換して、 switch 複数の代わりに if ステートメント:

package main

import "fmt"

func main() {
	flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}

	for _, flav := range flavors {
		switch flav {
		case "strawberry":
			fmt.Println(flav, "is my favorite!")
		case "vanilla", "chocolate":
			fmt.Println(flav, "is great!")
		default:
			fmt.Println("I've never tried", flav, "before")
		}
	}
}

出力は以前と同じです。

Output
chocolate is great! vanilla is great! strawberry is my favorite! I've never tried banana before

アイスクリームフレーバーのスライスをもう一度定義しました main と使用しました range 各フレーバーを反復するステートメント。 今回は、しかし、私たちは使用しました switch を調べるステートメント flav 変数。 2つ使用します case 設定を示す句。 もう必要ありません continue 1つだけのステートメント case 句はによって実行されます switch 声明。 複製されたロジックを組み合わせることができます "chocolate""vanilla" の宣言でそれぞれをコンマで区切ることによる条件 case 句。 The default 句は、キャッチオール句として機能します。 これは、本体で説明されていないすべてのフレーバーに対して実行されます。 switch 声明。 この場合、 "banana" 原因になります default 実行するには、メッセージを印刷します I've never tried banana before.

この簡略化された形式 switch ステートメントは、それらの最も一般的な使用法、つまり変数を複数の選択肢と比較することを扱います。 また、複数の異なる値に対して同じアクションを実行したい場合や、提供された条件を使用してリストされた条件のいずれも満たされない場合に他のアクションを実行したい場合にも便利です。 default キーワード。

この簡略化された形式の場合 switch 制限が多すぎることが判明した場合は、より一般的な形式を使用できます switch 声明。

一般的なSwitchステートメント

switch ステートメントは、より複雑な条件のコレクションをグループ化して、それらが何らかの形で関連していることを示すのに役立ちます。 これは、前の例のように特定の値ではなく、ある変数を値の範囲と比較するときに最も一般的に使用されます。 次の例は、を使用して推測ゲームを実装します if の恩恵を受ける可能性のあるステートメント switch 声明:

package main

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

func main() {
	rand.Seed(time.Now().UnixNano())
	target := rand.Intn(100)

	for {
		var guess int
		fmt.Print("Enter a guess: ")
		_, err := fmt.Scanf("%d", &guess)
		if err != nil {
			fmt.Println("Invalid guess: err:", err)
			continue
		}

		if guess > target {
			fmt.Println("Too high!")
			continue
		}

		if guess < target {
			fmt.Println("Too low!")
			continue
		}

		fmt.Println("You win!")
		break
	}
}

出力は、選択したランダムな数字とゲームのプレイの程度によって異なります。 1つのサンプルセッションからの出力は次のとおりです。

Output
Enter a guess: 10 Too low! Enter a guess: 15 Too low! Enter a guess: 18 Too high! Enter a guess: 17 You win!

私たちの推測ゲームでは、推測を比較するために乱数が必要なので、 rand.Intn からの機能 math/rand パッケージ。 のために異なる値を取得することを確認するには target ゲームをプレイするたびに、 rand.Seed 現在の時刻に基づいて乱数ジェネレーターをランダム化します。 議論 100rand.Intn 0〜100の範囲の数値が表示されます。 次に、 for ループして、プレーヤーからの推測の収集を開始します。

The fmt.Scanf 関数は、ユーザー入力を選択した変数に読み込む手段を提供します。 これは、ユーザーの入力を期待するタイプに変換するフォーマット文字列動詞を取ります。 %d ここでは、 int、およびのアドレスを渡します guess 変数 fmt.Scanf その変数を設定することができます。 解析エラーの処理の後、2つ使用します if ユーザーの推測を target 価値。 The string 彼らが戻ってくること bool、プレーヤーに表示されるメッセージと、ゲームを終了するかどうかを制御します。

これらは if ステートメントは、変数が比較されている値の範囲がすべて何らかの方法で関連しているという事実をあいまいにします。 また、範囲の一部を見逃したかどうかを一目で判断するのは難しい場合があります。 次の例では、前の例をリファクタリングして、 switch 代わりにステートメント:

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	target := rand.Intn(100)

	for {
		var guess int
		fmt.Print("Enter a guess: ")
		_, err := fmt.Scanf("%d", &guess)
		if err != nil {
			fmt.Println("Invalid guess: err:", err)
			continue
		}

		switch {
		case guess > target:
			fmt.Println("Too high!")
		case guess < target:
			fmt.Println("Too low!")
		default:
			fmt.Println("You win!")
			return
		}
	}
}

これにより、次のような出力が生成されます。

Output
Enter a guess: 25 Too low! Enter a guess: 28 Too high! Enter a guess: 27 You win!

このバージョンの推測ゲームでは、 if とのステートメント switch 声明。 式の引数を省略して switch 使用することにのみ興味があるので switch 条件文を一緒に収集します。 各 case 句には、比較する別の式が含まれています guess に対して target. 初めて交換したときと同じように if とのステートメント switch、もう必要ありません continue 1つだけからのステートメント case 句が実行されます。 最後に、 default 節は、次の場合を処理します guess == target 他のすべての可能な値を他の2つでカバーしたので case 条項。

これまで見てきた例では、1つのcaseステートメントが実行されます。 場合によっては、複数の動作を組み合わせたい場合があります case 条項。 switch ステートメントは、この動作を実現するための別のキーワードを提供します。

フォールスルー

別のコードを再利用したい場合があります case 句が含まれています。 このような場合、Goに次のボディを実行するように依頼することができます case を使用してリストされた句 fallthrough キーワード。 この次の例では、以前のアイスクリームフレーバーの例を変更して、ストロベリーアイスクリームに対する私たちの熱意をより正確に反映しています。

package main

import "fmt"

func main() {
	flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}

	for _, flav := range flavors {
		switch flav {
		case "strawberry":
			fmt.Println(flav, "is my favorite!")
			fallthrough
		case "vanilla", "chocolate":
			fmt.Println(flav, "is great!")
		default:
			fmt.Println("I've never tried", flav, "before")
		}
	}
}

次の出力が表示されます。

Output
chocolate is great! vanilla is great! strawberry is my favorite! strawberry is great! I've never tried banana before

前に見たように、私たちはのスライスを定義します string フレーバーを表現し、これを使用して反復します for ループ。 The switch ここでのステートメントは、前に見たものと同じですが、 fallthrough の最後にあるキーワード case の条項 "strawberry". これにより、Goはの本体を実行します case "strawberry":、最初に文字列を印刷します strawberry is my favorite!. 遭遇したとき fallthrough 次のボディを実行します case 句。 これはの体を引き起こします case "vanilla", "chocolate": 実行するには、印刷します strawberry is great!.

The fallthrough キーワードはGo開発者によって頻繁に使用されません。 通常、コードの再利用はを使用して実現されます fallthrough 共通のコードで関数を定義することで、より適切に取得できます。 これらの理由から、 fallthrough 一般的にはお勧めしません。

結論

switch ステートメントは、コードを読んでいる他の開発者に、一連の比較が何らかの形で相互に関連していることを伝えるのに役立ちます。 これらは、将来新しいケースが追加されたときに異なる動作を追加することをはるかに簡単にし、忘れたものがすべて適切に処理されることを保証することを可能にします default 条項。 次回、自分が複数の文章を書いていることに気付いたとき if すべて同じ変数を含むステートメントは、次のように書き直してみてください switch ステートメント—他の代替値を検討するときになると、やり直しが簡単になります。

Goプログラミング言語について詳しく知りたい場合は、Goシリーズのコーディング方法全体を確認してください。