Embedded struct tag reflect

I am trying to recurse through the struct tags for embedded structs.

This is the initial code, which gives a shallow report of struct tags

package main

import (
	"fmt"
	"reflect"
)

type Child struct {
	AA string `name:"alice"`
	BB string `name:"bella"`
}

type Parent struct {
	A string `name:"adrian"`
	Child
	B string `name:"bob"`
}

func report(defn any) {
	t := reflect.TypeOf(defn)
	fmt.Printf("\n-- Field <%s>\n", t.Name())
	for i := range t.NumField() {
		f := t.Field(i)
		name := f.Tag.Get("name")
		tname := f.Type.Name()
		fmt.Printf("Field tag(name) '%s' type '%s'\n", name, tname)
	}
}

func main() {
	report(Parent{})
	report(Child{})
}

When run this shows :

-- Field <Parent>
Field tag(name) 'adrian' type 'string'
Field tag(name) '' type 'Child'
Field tag(name) 'bob' type 'string'

-- Field <Child>
Field tag(name) 'alice' type 'string'
Field tag(name) 'bella' type 'string'

I want to report the Child struct tags from within the Parent struct…adding a recursive call (see further down or Go Playground - The Go Programming Language) shows

-- Field <Parent>
Field tag(name) 'adrian' type 'string'
Field tag(name) '' type 'Child'

-- Field <StructField>
Field tag(name) '' type 'string'
Field tag(name) '' type 'string'
Field tag(name) '' type 'Type'
Field tag(name) '' type 'StructTag'
Field tag(name) '' type 'uintptr'
Field tag(name) '' type ''
Field tag(name) '' type 'bool'
Field tag(name) 'bob' type 'string'

Does anyone know how I get the actual Child struct fields so I can iterate through them? Note this is for a more complex piece of code - I can only access the embedded struct through the parent (and I also have to change field values - not shown here).

Thank you - in advance - Andy

The amended code is below

package main

import (
	"fmt"
	"reflect"
)

type Child struct {
	AA string `name:"alice"`
	BB string `name:"bella"`
}

type Parent struct {
	A string `name:"adrian"`
	Child
	B string `name:"bob"`
}

func report(defn any) {
	t := reflect.TypeOf(defn)
	fmt.Printf("\n-- Field <%s>\n", t.Name())
	for i := range t.NumField() {
		f := t.Field(i)
		name := f.Tag.Get("name")
		tname := f.Type.Name()
		fmt.Printf("Field tag(name) '%s' type '%s'\n", name, tname)
		if tname == "Child" {
			report(f)
		}
	}
}

func main() {
	report(Parent{})
}

Instead of using name as marker for a embedded structure check its type.
func inspectValue(v reflect.Value, indent string) {
if !v.IsValid() {
return
}

switch v.Kind() {
case reflect.Struct:
	fmt.Printf("%sStruct (%s):\n", indent, v.Type())
	for i := 0; i < v.NumField(); i++ {
		field := v.Field(i)
		fieldType := v.Type().Field(i)
		fmt.Printf("%s  Field: %s\n", indent, fieldType.Name)
		inspectValue(field, indent+"    ") // Recursive call for nested struct fields
	}
case reflect.Slice, reflect.Array:
	fmt.Printf("%sSlice/Array (%s):\n", indent, v.Type())
	for i := 0; i < v.Len(); i++ {
		fmt.Printf("%s  Element %d:\n", indent, i)
		inspectValue(v.Index(i), indent+"    ") // Recursive call for slice/array elements
	}
case reflect.Map:
	fmt.Printf("%sMap (%s):\n", indent, v.Type())
	for _, key := range v.MapKeys() {
		val := v.MapIndex(key)
		fmt.Printf("%s  Key: %v\n", indent, key.Interface())
		inspectValue(val, indent+"    ") // Recursive call for map values
	}
default:
	fmt.Printf("%sValue: %v (Kind: %s)\n", indent, v.Interface(), v.Kind())
}

}

And the call inspectValue(reflect.ValueOf(Parent{}), “”)

I found another example that also set me on the value route :- success with this playground - Go Playground - The Go Programming Language

Essentially I needed to (outside the loop) -

	v := reflect.ValueOf(defn)

and then inside the loop add -

		vf := v.Field(i)
		if vf.Kind() == reflect.Struct {
			report(vf.Interface())
		}

Thank you for the reply - Andy