You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go反射函数中处理[]*Struct类型字段,访问嵌入结构体

解决Go反射中处理[]*struct类型字段的加密字段统计问题

我们需要修改现有的getEncFields函数,使其能够处理元素为结构体指针的切片类型(比如[]*Address),递归统计其中带bson:"encr"标签的字段。

原函数的问题

原函数仅处理了指针和结构体类型,没有针对切片类型做逻辑分支,导致遇到[]*struct这类字段时无法深入遍历内部结构体的加密字段。

修改后的完整代码

import "strings"

func getEncFields(t reflect.Type, list map[string]int) {
    // 先解多层指针
    for t.Kind() == reflect.Ptr {
        t = t.Elem()
    }

    // 处理结构体类型:遍历字段
    if t.Kind() == reflect.Struct {
        for i := 0; i < t.NumField(); i++ {
            field := t.Field(i)
            tag := field.Tag.Get("bson")
            if containsTag(tag, "encr") {
                list[getFieldName(field, tag)]++
            }
            // 递归处理字段类型
            getEncFields(field.Type, list)
        }
    }

    // 新增:处理切片类型,递归处理切片元素的类型
    if t.Kind() == reflect.Slice {
        elemType := t.Elem()
        getEncFields(elemType, list)
    }
}

// 判断bson标签中是否包含指定标记
func containsTag(tag, target string) bool {
    parts := strings.Split(tag, ",")
    for _, p := range parts {
        if p == target {
            return true
        }
    }
    return false
}

// 从字段或bson标签中获取字段名
func getFieldName(field reflect.StructField, tag string) string {
    parts := strings.Split(tag, ",")
    if len(parts) > 0 && parts[0] != "" {
        return parts[0]
    }
    return field.Name
}

改动说明

  1. 新增切片类型处理分支:当反射类型为reflect.Slice时,获取切片的元素类型,递归调用getEncFields处理该元素类型。
  2. 复用指针解引用逻辑:函数开头的指针解循环会自动处理切片元素中的指针类型(比如*Address),最终拿到底层的结构体类型进行遍历。
  3. 保持原有逻辑兼容:原有的结构体字段遍历、加密字段统计逻辑完全保留,不影响对普通结构体和指针字段的处理。

测试验证

使用示例结构体:

type Customer struct {
    Name     string    `json:"name" bson:"name"`
    Acnumber int64     `json:"acnumber" bson:"acnumber,encr"`
    Number   int64     `json:"number" bson:"number,encr"`
    Address  []*Address `json:"address" bson:"address"`
}

type Address struct {
    Mail string `json:"mail" bson:"mail,encr"`
}

调用函数并输出结果:

func main() {
    encList := make(map[string]int)
    getEncFields(reflect.TypeOf(Customer{}), encList)
    fmt.Println(encList) // 输出:map[acnumber:1 mail:1 number:1]
}

可以看到,Address切片内部的Mail字段已被正确统计。

内容的提问来源于stack exchange,提问作者Hariharan Panneerselvam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:23:17