インターフェース - Go

最終更新日: 2026-07-25

TOP(About this memo)) > 一覧(Go) > インターフェース

仕様

An interface type defines a type set. A variable of interface type can store a value of any type that is in the type set of the interface. Such a type is said to implement the interface. The value of an uninitialized variable of interface type is nil.

インターフェース型の定義

type iface struct {
	tab  *itab
	data unsafe.Pointer
}

interface{}

intefaceは何とでも比較ができる。

import "fmt"

func main() {
	//f0("aaaa")
	f1("aaaa")
	f1(1)
	f1(nil)
	f1((*int)(nil))
}	

func f0(a int) {
	fmt.Println(a == 1)
}

func f1(a any) {// any型として受け取る
	fmt.Println("---")
	fmt.Println(a == 1)// anyはどの型とも比較ができる
	fmt.Println(a == nil)
	fmt.Println(a == (*int)(nil))
}

インターフェース型の代入可能性

package main

func main() {
	f1(t1("test"))
	f2(t1("test"))
}

func f1(a i1) {
	t := a.(t1)// interfaceは具象の情報を持つのでアサーションが可能
	println(t.m2())
	println(a.m())
}

func f2[U i1](a U) {
	println(a.m())
}

//  i1 に関する記述は不要 であることが特徴
type t1 string

func (t t1) m() string {
	return string(t)
}

func (t t1) m2() string {
	return string(t) + string(t)
}

// interface
type i1 interface{ m() string }

nilはinterface型に代入可能

interface型からinterface型への代入可能性

type I interface{}
type I2 interface{ M() }
type I3 interface {
	M()
	N()
}

func main() {
	var i I
	var i2 I2
	var i3 I3

	i = i2
	i = i3
	// i2 = i // annot use i (variable of type I) as I2 value in assignment: I does not implement I2 (missing method M)
	i2 = i3
	// i3 = i2 //cannot use i2 (variable of type I2) as I3 value in assignment: I2 does not implement I3 (missing method N)
}
package main

func main() {
	f0(getErr())// こちらはOK: 実体がnilでもerror型として渡すことができる
	f1(getErr())// こちらはpanic
}

func getErr() error {
	// nilをerrorとして返すことができる。
	return nil
}

func f0(a error) error {
	return a// error型として受け取っているので、error型として返すことができる
}

func f1(a any) error {
	// return a// error型ではないのでコンパイルエラー
	return a.(error)// panic: any型として受け取ると、もうerror型にすることはできない。
}

インターフェース型のnilについて

package main

type MyError struct{}

func (e *MyError) Error() string { return "error!" }
func hoge() error {
	var myErr *MyError // この時点ではmyErr == nil
	// 処理中にエラーがあればmyErrに代入することを想定。
	return myErr
}

func fuge() error {
	return (*MyError)(nil)
}

func main() {
	println(hoge() == nil)             // falseになってしまう!
	println(hoge() == (*MyError)(nil)) // true

	println(fuge() == nil)             // falseになってしまう!
	println(fuge() == (*MyError)(nil)) // true
}
if エラーを検出 {
		return &MyError{}
	}
// 正常終了
return nil

typed nilはメソッドを実行してもpanicとならない

package main

type i interface {
	M()
}

type t string

func (tt *t) M() {
}

func main() {
	var ii i
	// ii.M()//  これは型情報の無いnilのためpanicとなる。
	var tt *t
	ii = tt
	ii.M()// これは型情報が入っているnilのためpanicとならない。
}

型アサーション(Type Assertions)

i := interface{}("hello")
s := i.(string)
var x float64 = 3.4
v := reflect.ValueOf(x) 
y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)
 i := interface{}("hello")
n, ok := i.(int)
fmt.Println(n, ok) // 0  false

参考

if pinger, ok := db.ConnPool.(interface{ Ping() error }); ok {
    err = pinger.Ping()
}
if driverCtx, ok := driveri.(driver.DriverContext); ok {
    ...
}

Type switches

i := interface{}("hello")
switch i.(type) {
	case string:
		fmt.Println("string")// string
	default:
		panic("")
}
func (db *DB) Select(query interface{}, args ...interface{}) (tx *DB) {
	...
    switch v := query.(type) {
	case []string:
		tx.Statement.Selects = v // この時点で vは []string型として扱える。
		for _, arg := range args {
			switch arg := arg.(type) {
			case string:
				...
			case []string:
				...
			default:
				...
			}
		}
    ...
	case string:
	...
}

caseの注意

switch vv := val.(type) {
	case bool:
		return GetZeroVal(vv)// これだと、vvは bool値になるが、
	case int, string:
		return GetZeroVal(vv)// これだと、vvは any型になる。(したがって意図した結果にならない。)
}
func GetZeroVal[R any](a R) R {
	return *new(R)
}

よく使われる標準パッケージのインターフェース

interfaceを実装した変数のポインター、の表現

type i interface{ f() }
type s struct{}

func (ss s) f() {}
func o(arg i)   {}

func main() {
	o(s{})
    // o(&s{}) //なんかこれでも行けた。
}
type i interface{ f() }
type s struct{}

func (ss s) f() {}
func o(arg *i)   {}
// func o[T i](arg *T) {} // これだと行ける。

func main() {
	// o(&s{}) //エラー
	o(new(i)) // *iを渡すと通る。
}

interfaceの埋め込み

General interfaces

// An interface representing only the type int.
interface {
	int
}

// An interface representing all types with underlying type int.
interface {
	~int
}

// An interface representing all types with underlying type int that implement the String method.
interface {
	~int
	String() string
}

// An interface representing an empty type set: there is no type that is both an int and a string.
interface {
	int
	string
}

generics

type HasID[T any] interface {
	GetID() string
	*T
}
type Pointer[T any] interface {
	*T
}