レシーバによる挙動の違いを強引に解決

Ken published on
2 min, 269 words

Categories: Programming

昨日のレシーバによる挙動の違いがとりあえず解決した。 解決というより、挙動がわかっていたからそれを使って実装したというだけであって、なんだこれ?って気がしないでもない。

なんだこれって思う部分はA構造体のSelfフィールドって、型は違えど同じAインスタンスというところ。

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

package main

import (
    "fmt"
    "reflect"
)

type I interface {
    Call()
    Method(interface{})
    SetSelf(I)
}

type A struct {
    Self I
    a1   bool
}

func (a *A) Call() {
    a.Self.Method(a.Self)
}
func (a *A) SetSelf(i I) {
    a.Self = i
}

func (a *A) Method(i interface{}) {
    ip := reflect.ValueOf(i)
    iv := ip.Elem()
    fmt.Println("name:", iv.Type().Name())
    for ii := 0; ii < iv.NumField(); ii++ {
        fmt.Println(iv.Field(ii))
    }
}

type B struct {
    A
    b1 int
    b2 float32
    b3 bool
}

func main() {
    var bi interface{}
    bi = &B{}
    t := reflect.TypeOf(bi).Elem()
    b := reflect.New(t)
    i, _ := b.Interface().(I)
    i.SetSelf(i)

    fmt.Println("----- invoke 'Method' via 'Call'. -----")
    i.Call()
    fmt.Println("----- invoke direct 'Method'. -----")
    i.Method(i)
}

/*
----- invoke 'Method' via 'Call'. -----
name: B
<main.A Value>
<int Value>
<float32 Value>
<bool Value>
----- invoke direct 'Method'. -----
name: B
<main.A Value>
<int Value>
<float32 Value>
<bool Value>
*/