Golang アサーションが失敗するのはなぜですか?それを避けるにはどうすればよいでしょうか?

PHPz
リリース: 2023-04-03 14:24:06
オリジナル
1522 人が閲覧しました

Golang は急速に発展しているプログラミング言語です。その構文は簡潔で、同時実行パフォーマンスに優れています。ますます多くの開発者に愛され、使用されています。ただし、このような効率的な言語であっても、予期せぬ問題が必ず発生します。 Golang でよくある問題の 1 つはアサーションの失敗 (Assertion Failed) です。

アサーションの失敗とは、プログラムの実行中に特定の条件が満たされず、プログラムがクラッシュすることを意味します。たとえば、アサーションを使用して特定のスライスの長さを決定する場合、スライスの長さが既知の制限より短い場合、プログラムはアサートに失敗します。このとき、プログラムはパニック エラー メッセージをスローし、プログラムの実行を続行できなくなります。

この種の問題は起こりにくいように見えますが、実際にはプログラムがクラッシュする可能性があります。したがって、アサーションが失敗する理由とそれを回避する方法を理解する必要があります。

アサーションが失敗する理由

  1. 初期化されていない変数

Golang では、変数が明示的に初期化されていない場合、この型の値はデフォルトでゼロになります。 。一部の値 (整数型など) では、ゼロ値は 0 であり、他の値では、nil または空のスライスです。

したがって、スライスや配列などの初期化されていない変数を操作すると、アサーションは失敗します。これらの変数のデフォルト値は nil 値であるため、その長さやインデックスを取得する方法はありません。この場合、アサーションの失敗を回避するには、可変長データ構造または配列要素を読み取る前に、必ず初期化または割り当てを行う必要があります。

  1. 配列またはスライスの範囲が範囲外です

Golang では、配列およびスライスへのアクセスは添字に基づいています。これは、無効な添え字を使用して配列またはスライスにアクセスすると、アサーションが失敗することを意味します。この状況は非常に一般的であり、ループ内で複数のインデックス変数を使用する場合に特にエラーが発生しやすくなります。

アサーションの失敗を回避するには、配列またはスライスにアクセスする前に、変数が範囲外にあるかどうかを確認する必要があります。比較演算子を使用して、長さ以上であるか、0 より小さいかを確認できます。

たとえば、次のコード スニペットは、スライスを安全に走査する方法を示しています。

slice := []int{1, 2, 3, 4, 5}
for i := 0; i < len(slice); i++ {
    if i >= len(slice) || i < 0 {
        // 索引越界
        break
    }
    // 访问数据
    fmt.Println(slice[i])
}
ログイン後にコピー
  1. 型アサーションが失敗しました

Golang では、多くの場合、次の操作が必要になります。インターフェイス型を実際の型に変換します。通常、この型変換を実行するには型アサーションを使用します。ただし、型の判定に失敗した場合、アサーションは失敗します。

型判定の失敗にはさまざまな理由が考えられます。たとえば、int へのポインターを文字列に変換しようとすると、アサーションは失敗します。また、インターフェイス型を変換できない型に変換しようとすると、アサーションは失敗します。

これを回避するには、正しい型判定を行い、常にリフレクションを使用してインターフェイスの型がターゲットの型と一致するかどうかを確認する必要があります。

アサーションの失敗を回避する方法

  1. 初期化と代入を通じて変数の有効な値を確保する

Golang では、通常、初期化されていない変数にはデフォルト値があります。値はゼロです。したがって、アサーションの失敗を回避するには、変数を使用する前に初期化するか、変数に有効な値を割り当てる必要があります。

たとえば、スライスの宣言と初期化は次のとおりです:

// 声明切片
var slice []int

// 初始化切片
slice = make([]int, 0)
ログイン後にコピー

あるいは、短い変数宣言を使用して変数を宣言し、初期化することもできます:

slice := make([]int, 0)
ログイン後にコピー
  1. インデックスの境界チェック

配列またはスライスの範囲が範囲外になるのを避けるために、インデックスの境界チェックを行う必要があります。比較演算子を使用すると、インデックスが 0 以上で、配列またはスライスの長さより小さいかどうかを確認できます。

たとえば、次は安全なスライス トラバーサルです:

// 安全获取数组元素的值
func safeGet(slice []int, index int) int {
    if index >= len(slice) || index < 0 {
        return -1
    }
    return slice[index]
}

func main() {
    slice := []int{1, 2, 3, 4, 5}

    // 遍历切片元素
    for i := 0; i < len(slice); i++ {
        fmt.Println(safeGet(slice, i))
    }
}
ログイン後にコピー
  1. 型アサーションを使用する前に、型が一致するかどうかを確認してください。

最後に、 use the type アサーションを行うときは、アサーションを行う前に、インターフェイスのタイプがターゲットのタイプと一致することを必ず確認してください。そうしないと、アサーションエラーが発生する可能性があります。

この状況を回避するには、リフレクション メカニズムを使用して型を検出します。たとえば、次のコード スニペットは、リフレクションを使用して値が文字列型であるかどうかを確認する方法を示しています。

// 判断一个值是否是字符串类型
func isString(val interface{}) bool {
    tt := reflect.TypeOf(val)
    if tt.Kind() == reflect.String {
        return true
    }
    return false
}

func main() {
    fmt.Println(isString("Hello, world!"))  // 输出 true 
    fmt.Println(isString(123))  // 输出 false 
}
ログイン後にコピー

結論

Golang アサーションの失敗は一般的な問題ですが、見落とされやすい問題でもあります。質問。これを回避するには、型アサーションを行う前に、変数を初期化して代入し、配列またはスライスで境界チェックを実行し、変数の型が一致していることを確認する必要があります。この方法によってのみ、アサーションの失敗によってプログラムがクラッシュしないようにすることができます。

以上がGolang アサーションが失敗するのはなぜですか?それを避けるにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート