Golang の interface 型 について。と型変換

golang における interface 型とは

var v interface{}

ゼロ個のメソッドを指定されたインターフェース型は、 空のインターフェース と呼ばれます:
空のインターフェースは、任意の型の値を保持できます。 (全ての型は、少なくともゼロ個のメソッドを実装しています。)

だそう。
ゼロ個のメソッド辺りがちょっとよく分からない。

型変換

interface{} 型はどんな値でも代入できる。
けど、型が定まってないので、代入は簡単だけど、扱うには少し大変。

interface{} → 任意の型

package main

import (
	"fmt"
)

func main() {

	var v interface{} = "もじ"
	// var v interface{} = false
	// var v interface{} = 0

	// 変換
	conv, ok := v.(string)
	// conv, ok := v.(bool)
	// conv, ok := v.(int)

	if !ok {
		fmt.Print("変換に失敗しました\n")
		return
	}

	fmt.Printf("型: %T, 値: %v\n", conv, conv)
}

interface{} → 構造体(struct)

やることはさほど変わらない。

package main

import (
	"fmt"
)

type Test struct {
	Name string
}

func main() {

	var v interface{} = Test{
	 	Name: "太郎",
	}
	// var v2 interface{} = &Test{
	// 	Name: "太郎",
	//}

	conv, ok := v.(Test)
	// conv, ok := v.(*Test)

	if !ok {
		fmt.Print("ERROR\n")
		return
	}

	fmt.Printf("%t, %v\n", conv, conv)
}

switch 文限定

switch 文で xxxx.(type) を使用して、
型を調べることもできる。
使い所がちょっと分からない。

package main

import (
	"fmt"
)

type Test struct {
	Name string
}

func main() {
	
	var v interface{} = "もじ"
	// var v interface{} = false
	// var v interface{} = 0
	// var v interface{} = Test{
	// 	Name: "太郎",
	// }

	switch v.(type) {
	case string:
		fmt.Print("i is string.\n")
	case bool:
		fmt.Print("i is bool.\n")
	case int:
		fmt.Print("i is int.\n")
	case int64:
		fmt.Print("i is int64.\n")
	case Test:
		fmt.Print("s is Test.\n")
	default:
	}
}

interface{} は型変換してから扱った方がいい

interface{} の仕様がよく分からない。
型は代入されたものでなんとなく判断してるぽい。

interface{} は非常に曖昧な印象を受けるので、
型変換してから扱うべきと思う。

下記、雑に interface{} について調べたコード。

package main

import (
	"fmt"
)

func test(v string) {
	fmt.Print(v, "\n")
}

func main() {
	
	// v には string が入ってるぽい
	var v interface{} = "もじ"
	var str string = "もじ"
	
	fmt.Print((v == str), "\n")// true
	
	
	var i int = 0
	var i2 int64 = 0
	
	// 当たり前だけどこちらは型が違うという旨のエラーが出る。
	fmt.Print((i == i2), "\n")
	// invalid operation: i == i2 (mismatched types int and int64)
	
	
	// i3 には int が入ってるぽい
	var i3 interface{} = 0
	fmt.Print((i3 == i), "\n")// true
	fmt.Print((i3 == i2), "\n")// false。エラーは出ない
	
	
	// 関数の引数として使うと、interface 型は string 型として扱えない。
	// まず v の型をはっきりさせて。という旨のエラーが出る
	//
	test(v)
	// cannot use v (variable of type interface{}) as string value in argument to test: need type assertion
}
カテゴリー:Go