【GO言語の基礎】GOの3大プロセスで習得しなければならない基本スキル(4)

プロセス制御

プログラムでは、プログラム操作のフロー制御によって、プログラムの実行方法が決まります。これは、マスターする必要があるものです。3つの主要なフロー制御ステートメントがあります。

  • シーケンス制御
  • ブランチコントロール
  • ループ制御

シーケンス制御

プログラムは、判断や途中でジャンプすることなく、上から下に1行ずつ実行されます。

ブランチコントロール

プログラムを選択的に実行するための分岐制御には、次の3つのタイプがあります。

  • シングルブランチ
    if 条件表达式 {
        //执行代码块
    }
  • ダブルブランチ
    if 条件表达式 {
        //执行代码块
    } else {
        //执行代码块
    }
  • マルチブランチ
    if 条件表达式1 {
        //执行代码块 
    } else if 条件表达式2 {
        //执行代码块
    } else {
        //执行代码块
    }

    //在符合一个条件 执行相应代码块后 会结束
  1. コードを1行しか記述しない場合でも、{}は必須です。
  2. 条件式には括弧は必要ありません
  3. ブロックで宣言された変数のスコープはブロック内のみです
  4. golangは、ifで変数を直接定義することをサポートします
    if age := 20; age > 18 { 
        //代码块
    } 
  1. ifステートメントの条件式を代入ステートメントにすることはできません
    if b = false { //错误

    } 
  1. ifステートメントの条件式の結果はbool値でなければなりません
    n := 4 if n { //错误

    }

スイッチ

switchステートメントは、さまざまな条件に基づいてさまざまなアクションを実行するために使用されます。各ケースブランチは一意であり、一致する位置まで上から下に1つずつテストされます。

試合後に休憩を追加する必要はありません

基本構文:

    switch 表达式 {
        case 表达式1,表达式2, ... :
            语句块
        case 表达式3,表达式4, ... :
            语句块
        case 表达式5:
            语句块
        default:
            语句块
    }
  1. switchの実行フローは、最初に式を実行し、値を取得してから、case式と比較することです。等しい場合は一致し、対応するcaseステートメントブロックを実行してから、switchコントロールを終了します。それらの一致、デフォルトが実行されます。
  2. デフォルトのステートメントは必要ありません。
  3. switch式の値がどのcase式とも正常に一致しない場合、デフォルトのステートメントブロックが実行されます。実行後、スイッチ制御を終了します。
  4. golangの場合の後に、コンマで区切られた複数の式が存在する場合があります。
  5. golangのcaseステートメントブロックはbreakを書き込む必要はありません。これは、デフォルトで、つまり、プログラムがcaseステートメントブロックの実行を終了すると、スイッチ制御構造を直接終了するためです。
  6. フォールスルー:これは、次のケース条件との論理OR関係です。これは、次のケースに論理OR条件を追加することと同じです。
  7. ケースの後の各式の値のデータ型は、スイッチ式のデータ型と同じである必要があります
package main

import "fmt"

func main() {

    var num1 int32 = 20
    var num2 int64 = 20

    switch num1 {

    case num2:
        fmt.Println("相等呢")
    case 30:
        fmt.Println("哈哈")

    }
}
//运行时报错
invalid case num2 in switch on num1 (mismatched types int64 and int32)

ただし、数字の場合は、数字自体にタイプがないため、問題ありません。

package main

import "fmt"

func main() {

    var num1 int32 = 20

    switch num1 {

    case 20.0:
        fmt.Println("相等呢")
    case 30:
        fmt.Println("哈哈")

    }
}

  1. golangで切り替えた後の表現も必要ありません
  2. type switch
    switchステートメントをtype-switchで使用して、インターフェイス変数に実際に格納されている変数のタイプを判別することもできます。
    タイプスイッチの構文形式は次のとおりです。
    switch x.(type) {
    case type:
        statement(s);
        case type:
        statement(s);
        //你可以定义任意个数的case
        default: /*可选*/
        statement(s);
    }

例:

    package main

    import "fmt"

    func main() {

        var x interface{}

        switch i := x.(type) { //x.()格式是类型断言
        case nil:
            fmt.Printf("x 的类型是: %T", i)
        case int:
            fmt.Printf("x 的类型是: int")
        case float64:
            fmt.Printf("x的类型是: float64")
        case func(int) float64:
            fmt.Printf("x的类型是: func(int)")
        case bool, string:
            fmt.Printf("x的类型是: bool或string")
        default:
            fmt.Printf("未知型")
        }
    }
    //以上代码的执行结果为:
    x 的类型是: <nil>

  1. ケースの後には式(つまり、定数値、変数、戻り値を持つ関数など)があります。
  2. 大文字と小文字の後ろの式が定数値(リテラル)の場合、繰り返さないでください
    package main

    import "fmt"

    func main() {

        var n1 int32 = 5
        var n2 int32 = 20
        var n3 int32 = 5
        switch n1 {

            case n2, 10, 5:
                fmt.Println("case1")
            case 5: //这里不允许重复出现数字5,但是如果我们把5替换成变量n3就不会报错
                fmt.Println("case2")
        }
    }

  1. 切り替えの直後にセミコロンで終わる変数を宣言/定義することもできますが、お勧めしません
    switch grade := 90; {
        case grade > 90:
        fmt.Println("成绩优秀...")
        case grade >= 60 && grade <= 90:
        fmt.Println("成就优良")
        default:
        fmt.Println("不及格")
    }

  1. スイッチとifの比較

判断する特定の値が多くなく、整数、浮動小数点数、文字、文字列のタイプに準拠している場合は、簡潔で効率的なswitchステートメントを使用することをお勧めします。
その他の状況:間隔の判断および結果がブール型であるとの判断に使用し、使用範囲が広い場合\

ループ制御

Go言語のloopステートメントは、forキーワードのみをサポートし、whileおよびdo-where構造はサポートしません。

ために

構文:
Go言語には3つの形式のforループがあり、そのうちの1つだけがセミコロンを使用します。

  • C言語の場合と同じ:
    • init:通常、これは代入式であり、制御変数に初期値を割り当てます。

    • 条件:関係式または論理式;ループ制御条件

    • post:通常、代入式、制御変数をインクリメントまたはデクリメントします。

for init; condition; post {}

  • Cのwhileと同じ:
    • 変数の初期化と変数の反復を他の場所に書き込む
for condition {}

  • Cのfor(;;)と同じ:
    • forループ内にbreakステートメントがない場合、永久にループします。通常は、breakステートメントと一緒に使用する必要があります。
for {}

  • forループの範囲形式は、スライス、マップ、配列、文​​字列などを繰り返しループできます。形式は次のとおりです。

    • 文字列トラバーサル法1-従来の方法
        var str string = "hello, world"
        for i := 0; i < len(str); i++ {
            fmt.Printf("%c \n", str[i])
        }
    
    
    • 文字列走査法2-for-range
        var str string = "hello, world"
        for key, value := range str {
            fmt.Printf("key=%d, value=%c \n", key, value)
        }
    
    

質問:文字列に中国語が含まれている場合、文字列をトラバースする従来の方法が間違っており、文字化けした文字が表示されます。その理由は、文字列の従来のトラバーサルはバイト単位でトラバースされ、漢字はutf8エンコーディングでは3バイトに対応するためです。
解決方法:strを[]ルーンスライスに変換する必要があります。for-rangeトラバーサルメソッドに対応して、文字でトラバースされます。したがって、中国語の文字列がある場合は、それも可能です

ブレーク

breakステートメントは、ステートメントブロックの実行を終了したり、現在のforループを中断したり、switchステートメントからジャンプしたりするために使用されます。休憩は、ループ全体から飛び出すことです。

breakステートメントがマルチレベルのネストされたステートメントブロックに表示される場合、ラベルを使用して、ステートメントブロックのどのレベルを終了するかを示すことができます。

    package main
    import "fmt"

    func main() {
        //label1:
        for i := 0; i < 4; i++ {
            label2:
            for j := 0; j < 5; j++ {
                if j == 2 {
                    //break  //break默认会跳出最近的循环
                    //break label1;
                    break label2;
                }
                fmt.Println("j = ", j)
            }
        }
    }

継続する

continueステートメントは、このループを終了し、次のループの実行を継続するために使用されます。

マルチレベルのネストされたループステートメントの本体にcontinueステートメントが表示されている場合、ラベルを使用して、スキップするループのレベルを知ることができます。これは、前のbreak + labelと同じです。

後藤

  • Go言語のGotoステートメントは、プログラム内の指定された行に無条件に移動できます。
  • gotoステートメントは通常、条件ステートメントと組み合わせて使用​​されます。条件付き遷移の実現、ループからのジャンプ、その他の機能に使用できます。
  • Goプログラミングでは、プログラムフローを混乱させたり、プログラムの理解とデバッグを困難にしたりしないようにgotoステートメント使用一般的に推奨されていません。
    文法:
    goto label

    label: statement

例:

    package main
    import "fmt"

    func main() {
        fmt.Println(1);
        goto label1
        fmt.Println(2);
        fmt.Println(3);
        fmt.Println(4);

        label1:
        fmt.Println(5);
    }
    //输出结果
    1
    5

戻る

returnは、メソッドまたは関数で使用され、終了するメソッドまたは関数を示します。

  1. returnが通常の関数の場合は、関数が終了したこと、つまり関数のreturnの後のコードが実行されなくなったことを意味し、終了関数としても理解できます。
  2. returnがmain関数にある場合は、main関数が終了している、つまりプログラムが終了していることを意味します。

延期

関数が戻る前に、関数のクリーンアップを簡素化するために、defer関数の操作が呼び出されます。

  1. 延期式が決定されると、延期修正関数(以下、総称して延期関数と呼ぶ)のパラメータも決定される。
  2. 関数内に複数の遅延関数が存在する可能性がありますが、これらの遅延関数は、関数が戻るときに後入れ先出しの原則に従います。
  3. 関数名の戻り値は、遅延関数で使用されます

関数の戻り値はdeferによって変更される場合があります。本質的な理由は、return xxxステートメントがアトミック命令ではないためです。実行プロセスは次のとおりです。戻り値を保存する(存在する場合)-> deferを実行する(存在する場合)->リターンジャンプを実行します。

パニック(例外をスローするのと同じ)

パニックは、プログラムの実行フローを停止できる組み込み関数です。

  1. 呼び出し元関数の実行は、現在の呼び出しポイントから終了します
  2. 戻り値はパニックを介して設定できます

パニックの意味は、例外処理プロセスを制御するだけでなく、例外の原因を返すことでもあります。
パニックが例外の原因を呼び出し元に返さない場合、呼び出し元は問題に対処する方法がありません。したがって、パニックが呼び出されると、通常、失敗の理由を示す文字列が返されます。
パニックの戻り値は、recover関数を介して取得されます。

  1. パニックを呼び出す前の延期操作は、パニックを呼び出した直後に実行されます。

回復(例外のキャッチと同等)

回復関数も組み込み関数であり、特にパニック関数の戻り値を受け取るために使用されます。パニック関数が呼び出されないか、戻り値がない場合、recoverはNilを返します。
キャプチャ関数recoverは、遅延呼び出し内で直接呼び出された場合にのみエラーで終了します。それ以外の場合は、常にnilを返します。キャッチされなかったエラーは、コールスタックに沿って渡されます。

おすすめ

転載: blog.csdn.net/weixin_54707168/article/details/113934012