Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

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

http://play.golang.org/p/qsTwrL11mu

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{}にしておき、任意の関数を渡し、リフレクションして呼び出す。

http://play.golang.org/p/fFmGNRlqcn

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)
}
tenntenn
Go engineer / Gopher artist
mercari
フリマアプリ「メルカリ」を、グローバルで開発しています。
https://tech.mercari.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away