🌀

Goにおける型アサーションと型キャストの違いを理解しよう

2024/11/13に公開

型アサーションと型キャストの違いについて ✨

こんにちは!今回はGolangの「型アサーション」と「型キャスト」について解説します🚀。Goを使っていると、「これって型アサーション?それとも型キャスト?」と迷うことがありますよね。実際、この2つは似ているようで全然違うんです。

💡 型アサーションとは?

型アサーションは、どんな具体的な型の値も格納できるインタフェース型から具体的な値を取り出すために使います。

例を見てみましょう 👀

package main

import "fmt"

func main() {
	var a any = "hello"

	// any 型から string 型に型アサーション
	s, ok := a.(string)
	if ok {
		fmt.Println("string型です:", s)
	} else {
		fmt.Println("string型ではありません")
	}

	// any 型から int 型に型アサーションに失敗する場合
	_, ok = a.(int)
	if !ok {
		fmt.Println("int型ではありません")
	}
}

👆 このコードでは、any 型の変数 a から string 型を取り出しています。型アサーションは、変数.(型) のように記述します。もしアサーションに成功すれば、インタフェース型(any または interface{})に格納された値が指定した型(ここでは string)であることが確認され、値が取り出されます。これを「カンマ ok イディオム」と呼び、成功時には型が一致した値が取り出され、失敗時にはその型のゼロ値(この場合、空文字列 ""0)が返されます。

⚠️ カンマ ok イディオム は型アサーション以外の場でも使われるため、型アサーションに限定された構文ではありません。

また、ok には型が一致したかどうかの真偽値が格納されるため、プログラムがパニックすることなく型チェックを行えます。

📝 ポイント: 型アサーションは、インタフェース内の値の型を確認しながら安全に取り出すための手法です。型キャストではないので注意しましょう。

✒ なぜ「型アサーション」と呼ぶのか

「型アサーション(assertion)」という言葉が使われる理由は、特定の型であることを「断言」する操作を表しているためです。Goの型アサーションでは、interface や any 型に格納された値が特定の型であることを確認し、取り出そうとします。ここで使われる「assertion(アサーション)」は、「ある型であると確認する、断言する」という意味を持っており、型アサーションによってその型が一致しているかどうかを検証できるのです。

🛠️ 型キャストとは?

一方で、型キャストは明示的に型を変換することを指します。例えば、int から float64 へ変換したり、float64 から int へ変換したりします。

例を見てみましょう 👇

package main

import "fmt"

func main() {
	var n int = 42

	// int 型から float64 型に型キャスト
	var f float64 = float64(n)
	fmt.Printf("intからfloat64へ変換: %f\n", f)

	// float64 型から int 型に型キャスト
	var i int = int(f)
	fmt.Printf("float64からintへ変換: %d\n", i)
}

👆 このコードでは、intfloat64 に型キャストし、逆に float64 から int に型キャストしています。型キャストは、型(変数)のように記述します。型キャストは値の型そのものを変換するので、異なるメモリ表現に変換されます。

📝 ポイント: 型キャストは、データのメモリ表現を変換する操作です。

✒ なぜ「型キャスト」と呼ぶのか

「キャスト(cast)」という用語は、異なる型間で値を「変換する」操作を指すために使われています。英語の "cast" には「鋳造する」や「変える」という意味があり、プログラミングにおける「キャスト」は、ある型の値を一時的に別の型の表現に変える操作です。Goの型キャストでは、型(変数) の形式で明示的に型を変換し、メモリ表現を変更するため、「キャスト」という言葉が使われています。

✨ 違いを整理しましょう!

  • 型アサーション: インタフェース型から具体的な型を取り出す方法。
    • 利用方法:型アサーションで取り出した値, 型アサーションの成功の有無 := インタフェース型の変数.(型アサーションしたい型)
  • 型キャスト: 値の型そのものを明示的に変換する方法。
    • 利用方法:型キャストされた変数 := 型キャストしたい型(型キャストしたい変数)
型アサーションと型キャストの細かな違い

型アサーションは実行時に判定されますが、一方で型キャストはコンパイル時に判定されます。

下記のコードを go build してみてください。不適切な型キャストを行っている変数 n3 についてのみ指摘されます。

package main

import "fmt"

func main() {
	var a any = 1
	n, ok := a.(int)
	fmt.Printf("n: %d, ok: %v\n", n, ok)

	var a2 any = "hello"
	n2, ok := a2.(int)
	fmt.Printf("n: %d, ok: %v\n", n2, ok)

	var n3 string = "abc"
	i := int(n3)
	fmt.Printf("i: %d\n", i)

}

変数 n3 周辺を削除したうえで実行すると出力は下記の通りになります。

n: 1, ok: true
n: 0, ok: false

上記の実験から、型キャストはコンパイル時、型アサーションは実行時に判定されることがわかります。

型アサーションは、「インタフェース型」から取り出すときにしか使えない点に注意しましょう。逆に、型キャストはすべての互換性のある型同士で利用できます。

おわりに 🎉

型アサーションと型キャスト、どちらもGolangを扱う上で知っておくべき基本的な概念です。それぞれの違いを理解して、適切に使い分けることで、コードがより良くなります!

今回紹介したコードを実際に動かしてみて、ぜひ違いを実感してくださいね!Happy Coding ✨

Discussion