MST

星途 面试题库

面试题:Go中接口与反射结合处理复杂结构体嵌套的技巧

给定一个复杂嵌套的结构体,例如结构体A包含结构体B,结构体B又包含其他基本类型和切片等。使用Go的接口和反射实现一个通用函数,该函数能够遍历整个结构体并将所有字段值打印出来,要求能够处理不同类型的字段,包括嵌套结构体和切片等复杂情况。
11.6万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "reflect"
)

type B struct {
    Field1 string
    Field2 int
    Field3 []float64
}

type A struct {
    InnerB B
    Field4 bool
    Field5 []string
}

func printStructFields(i interface{}) {
    value := reflect.ValueOf(i)
    if value.Kind() == reflect.Ptr {
        value = value.Elem()
    }
    if value.Kind() != reflect.Struct {
        fmt.Println("Input is not a struct")
        return
    }

    printFieldsRecursive(value, "")
}

func printFieldsRecursive(value reflect.Value, prefix string) {
    for i := 0; i < value.NumField(); i++ {
        field := value.Field(i)
        fieldName := prefix + value.Type().Field(i).Name

        switch field.Kind() {
        case reflect.Struct:
            printFieldsRecursive(field, fieldName+".")
        case reflect.Slice:
            fmt.Printf("%s: []\n", fieldName)
            for j := 0; j < field.Len(); j++ {
                item := field.Index(j)
                if item.Kind() == reflect.Struct {
                    printFieldsRecursive(item, fieldName+"["+fmt.Sprintf("%d", j)+"].")
                } else {
                    fmt.Printf("%s[%d]: %v\n", fieldName, j, item.Interface())
                }
            }
        default:
            fmt.Printf("%s: %v\n", fieldName, field.Interface())
        }
    }
}

func main() {
    a := A{
        InnerB: B{
            Field1: "Hello",
            Field2: 42,
            Field3: []float64{1.1, 2.2, 3.3},
        },
        Field4: true,
        Field5: []string{"a", "b", "c"},
    }
    printStructFields(a)
}

在上述代码中:

  1. printStructFields 函数是对外暴露的接口,它首先检查传入的参数是否为指针,如果是则取其指向的值,然后检查值是否为结构体类型。如果不是结构体类型则输出错误信息并返回。
  2. printFieldsRecursive 函数是一个递归函数,用于遍历结构体的字段。
    • 对于结构体字段,递归调用 printFieldsRecursive 继续遍历。
    • 对于切片字段,先打印切片的开头,然后遍历切片元素。如果元素是结构体,则递归调用 printFieldsRecursive;否则直接打印元素值。
    • 对于其他类型的字段,直接打印字段名和字段值。

main 函数中,创建了一个 A 结构体实例并调用 printStructFields 函数打印其所有字段值。