-1

I try to understand the correct usage of reflection with a struct compose by nested structs that implement an interface on Golang;

Here the code:

package main

import (
    "log"
    "reflect"
)

// Macro is the main struct and contain the two nested structs that implement the interface PrintStr
type Macro struct {
    Field1 Test
    Field2 Test
}

// PrintStr interface that define a single method Print
type PrintStr interface {
    Print() // method that will print the struct content
}

// Test is a simple struct with a single field of type string that implement the PrintStr interface
type Test struct {
    str string
}

// Print implementation of interface function
func (t *Test) Print() {
    log.Println(t.str)
}

func main() {
    test := Macro{
        Field1: Test{
            str: "field1",
        },
        Field2: Test{
            str: "field2",
        },
    }
    
    // the idea is to cycle the struct 'test' fields and launch the method Print using the reflection
    values := reflect.ValueOf(&test)
    if values.Kind() == reflect.Ptr {
        values = values.Elem()
    }

    // cycling the fields
    for i := 0; i < values.NumField(); i++ {
        switch v := values.Field(i).Interface().(type) {
        case PrintStr:
            v.Print()
            break

        default:
            log.Fatal("ErrUnhandledType")
        }
    }
}

if I execute this code, I obtain the follow result:

2025/05/09 15:35:26 ErrUnhandledType

instead, if I edit the switch an I use the Struct that implement the interface...

...
    // cycling the fields
    for i := 0; i < values.NumField(); i++ {
        switch v := values.Field(i).Interface().(type) {
        case Test:
            v.Print()
            break

        default:
            log.Fatal("ErrUnhandledType")
        }
    }
...

I obtain the expected result:

2025/05/09 15:47:44 field1
2025/05/09 15:47:44 field2

The final result I want to archive is to create a working code that don't know the final structs that implement the interface PrintStr ma only the interface itself.

Is this possible?

0

1 Answer 1

6

Because the Print method is on the pointer receiver, the type Test does not implement PrintStr.

Here are two options for fixing the problem.

Option 1: Use the address of the field. The value of values.Field(i).Addr().Interface() is a *Test, which does implement the interface.

switch v := values.Field(i).Addr().Interface().(type) 

https://go.dev/play/p/ElJamDeiwSB

Option 2: Declare method on value receiver. With this change, type Test implements the interface.

func (t Test) Print() {

https://go.dev/play/p/uAfWzYzBmiX

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.