samedi 20 juin 2020

Golang : Dynamic Pointer to Struct is missing Embedded Struct's methods but works without pointer reference

I've 2 structs, Both embedded another struct called Test.

The struct Created at Compile time EmbeddedCompiledStruct is able to access the Method from Test struct. However the Dynamically created Struct is able to access the Method only if it is accessed via the struct but not via its Pointer.

// Test ...
type Test struct {
    Name string
}

// TableName ...
func (Test) TableName() string {
    fmt.Printf("MyTableName called")
    return "MyTableName"
}

// EmbeddedCompiledStruct ...
type EmbeddedCompiledStruct struct {
    Test
}

type tabler interface {
    TableName() string
}

func main() {
    structFields := []reflect.StructField{
        {
            Name:      "Type",
            Type:      reflect.TypeOf(Test{}),
            Tag:       `json:"-" gorm:"-"`,
            Anonymous: true,
        },
        {
            Name: "Name",
            Type: reflect.TypeOf(""),
            Tag:  `json:"name,omitempty" gorm:"column:Name;not null;size:16;primary_key"`,
        },
    }
    
    structDec := reflect.StructOf(structFields)
    compiledStruct := reflect.TypeOf(EmbeddedCompiledStruct{})

    // Normal Structs 
    fmt.Printf("\nType Dynamic Embedded Struct Methods : %+v\n", structDec)
    for i := 0; i < structDec.NumMethod(); i++ {
        fmt.Println(structDec.Method(i).Name)
    }
    fmt.Printf("\nType Compiled Embedded Struct Methods : %+v\n", compiledStruct)
    for i := 0; i < compiledStruct.NumMethod(); i++ {
        fmt.Println(compiledStruct.Method(i).Name)
    }
    
    // Pointer to Structs
    t1 := reflect.TypeOf(reflect.New(structDec).Interface())
    fmt.Printf("\nType Dynamic Embedded Struct Pointer Methods : %+v\n", t1)
    // -----> Here its missing TableName Method
    for i := 0; i < t1.NumMethod(); i++ {
        fmt.Println(t1.Method(i).Name)
    }

    t3 := reflect.TypeOf(reflect.New(compiledStruct).Interface())
    fmt.Printf("\nType Compiled Embedded Struct Pointer Methods : %+v\n", t3)
    for i := 0; i < t3.NumMethod(); i++ {
        fmt.Println(t3.Method(i).Name)
    }

    fmt.Println("")
    if tabler, ok := reflect.New(structDec).Interface().(tabler); ok {
        fmt.Println("Convertible Dynamic Struct " + tabler.TableName())
    } else {
        fmt.Println("Not convertible Dynamic Struct")
    }

    if tabler, ok := reflect.New(compiledStruct).Interface().(tabler); ok {
        fmt.Println("Convertible Compiled Struct " + tabler.TableName())
    } else {
        fmt.Println("Not convertible Compiled Struct")
    }
}

Output:

Type Dynamic Embedded Struct Methods : struct { Type main.Test "json:\"-\" gorm:\"-\""; Name string "json:\"name,omitempty\" gorm:\"column:Name;not null;size:16;primary_key\"" }
TableName

Type Compiled Embedded Struct Methods : main.EmbeddedCompiledStruct
TableName

Type Dynamic Embedded Struct Pointer Methods : *struct { Type main.Test "json:\"-\" gorm:\"-\""; Name string "json:\"name,omitempty\" gorm:\"column:Name;not null;size:16;primary_key\"" }

Type Compiled Embedded Struct Pointer Methods : *main.EmbeddedCompiledStruct
TableName

Not convertible Dynamic Struct
MyTableName calledConvertible Compiled Struct MyTableName

The t1 Object doesn't Print the method name TableName. However the object created from Compiled Struct works fine in both scenario's even though they embed the same struct.

Why is DynamicStruct Pointer not able to Get the Embedded Methods but a Compiled Struct is able to do it? Is this a bug of some sort in Golang?

Playground : https://play.golang.org/p/zrWP0WfL9lQ





Aucun commentaire:

Enregistrer un commentaire