65
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Go言語におけるinterface{}とリフレクションを使ったパターン

Last updated at Posted at 2013-09-19

出力引数としてinterface{}を受け取る

設定したい変数のポインタをinterface{}として受け取る。
interface{}なので、任意の型を渡すことができる。
reflect.ValueOfreflect.Value型に変換する。
その後、Value.Elem()でポインタが指している先を取得して、Value.Set()で値を設定する。

reflect_pattern1.go
package main

import (
	"fmt"
	"reflect"
)

func set(p, v interface{}) error {
	pv := reflect.ValueOf(p)
	if pv.Kind() != reflect.Ptr {
		return fmt.Errorf("p must be pointer.")
	}

	vv := reflect.ValueOf(v)
	if pv.Elem().Kind() != vv.Kind() {
		return fmt.Errorf("p type and v type do not mutch")
	}

	pv.Elem().Set(vv)

	return nil
}

func main() {
	var hoge int
	fmt.Println(hoge)
	set(&hoge, 100)
	fmt.Println(hoge)
	fmt.Println(set(&hoge, 10.4))
}

関数をinterface{}で受け取る

関数は引数や戻り値を含めて型なので、引数や戻り値が一致しないと同じ型として扱うことができない。そのため、引数の型をinterface{}にしておき、任意の関数を渡し、リフレクションして呼び出す。

reflect_pattern2.go
package main

import (
	"fmt"
	"reflect"
)

func call(f interface{}) {
	fv := reflect.ValueOf(f)
	if fv.Kind() != reflect.Func {
		panic("f must be func.")
	}
	fv.Call([]reflect.Value{})
}

func main() {
	f := func() {
		fmt.Println("hello!")
	}
	call(f)
}
65
42
0

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
65
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?