0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Goの型アサーションを理解する

Last updated at Posted at 2025-03-19

はじめに

Goを使っていると、以下のような 型アサーションエラー に遭遇することがあります。

impossible type assertion: comp.(*ExampleService)
*ExampleService does not implement Component (missing method Name)

このエラーの原因は、インターフェースを満たしていないことですが、Goの型システムを理解していないと解決が難しい場合があります。

1. Goの型アサーションとは?

型アサーションとは、インターフェース型の値を具体的な型に変換する 方法です。

基本的な型アサーション

var i interface{} = "hello"

s := i.(string) // 型アサーション:interface{} を string に変換
fmt.Println(s) // "hello"

このコードでは、iinterface{}型ですが、(string) を使うことで string 型として扱えます。

2. 型アサーションが失敗する場合

型アサーションは、間違った型に変換しようとすると panic を発生 させます。

var i interface{} = "hello"

n := i.(int) // panic: interface conversion: string is not int
fmt.Println(n)

このような panic を防ぐために、Goには 安全な型アサーション の書き方が用意されています。

3. 安全な型アサーションの書き方

Goでは、型アサーションが失敗したときに false を返す方法があります。

var i interface{} = "hello"

s, ok := i.(string) // 型アサーションが成功する場合
if ok {
    fmt.Println("変換成功:", s)
} else {
    fmt.Println("変換失敗")
}

n, ok := i.(int) // 型アサーションが失敗する場合
if !ok {
    fmt.Println("型アサーションが失敗しました") // こちらが実行される
}

4. インターフェースを型アサーションする

Goでは、インターフェースから具体的な型に変換することもできます。

type Component interface {
	Name() string
}

type ExampleService struct{}

func (s *ExampleService) Name() string {
	return "example"
}

func main() {
	var comp Component = &ExampleService{}

	// 安全な型アサーション
	service, ok := comp.(*ExampleService)
	if !ok {
		fmt.Println("型アサーション失敗")
		return
	}
	fmt.Println("変換成功:", service.Name())
}

このコードでは、Component インターフェースを *ExampleService に変換しています。
ok をチェックすることで、安全に実行できます。

5. 型アサーションの落とし穴

(1) インターフェースを満たしていない場合

type Component interface {
	Init() error
}

type ExampleService struct{}

func main() {
	var comp Component = &ExampleService{}

	service, ok := comp.(*ExampleService) // これはエラー!
	if !ok {
		fmt.Println("型アサーション失敗")
	}
}

この場合、ExampleServiceInit() メソッドがないため、Component を満たしていません。
解決策 として、Init() メソッドを実装する必要があります。

func (s *ExampleService) Init() error {
	return nil
}

(2) nil のチェックを忘れる
⚠️ nilチェックしたあとでもpanicする場合があるのでコメントをチェックして下さい

var comp Component

service, ok := comp.(*ExampleService) // これは `nil` になる可能性がある!

comp が nil の場合、型アサーションは false を返しますが、型が一致していると勘違いして nil のまま進んでしまうことがあります。

解決策

if comp == nil {
    fmt.Println("comp は nil です")
} else if service, ok := comp.(*ExampleService); ok {
    fmt.Println("型アサーション成功")
}

まとめ

  • 型アサーションは、インターフェース型の値を具体的な型に変換する方法
  • s := i.(string) は 失敗すると panic する ので注意
  • 安全な型アサーション (s, ok := i.(string)) を使うと ok で成否を確認できる
  • インターフェースを型アサーションするときは、事前に nil チェック も忘れずに
0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?