0

0

如何在 Go 中遍历结构体时排除空字段(零值或 nil 字段)

霞舞

霞舞

发布时间:2025-12-29 18:11:04

|

981人浏览过

|

来源于php中文网

原创

如何在 Go 中遍历结构体时排除空字段(零值或 nil 字段)

本文介绍如何使用反射动态获取结构体中非空(非零值、非 nil)字段的名称,适用于表单解析、api 参数过滤等场景。

在 Go 中,结构体字段默认具有其类型的零值(如 string 为 "",int 为 0,指针/切片/映射为 nil)。当从用户输入(如 HTTP 表单或 JSON)初始化结构体后,我们常需仅处理“真正被设置”的字段——即排除所有零值或 nil 的字段。这无法通过简单的字段名遍历实现,而需结合 reflect 包对每个字段值进行语义化判空。

以下是一个健壮、可复用的判空函数,支持常见类型:

func isEmpty(v reflect.Value) bool {
    switch v.Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return v.Int() == 0
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
        return v.Uint() == 0
    case reflect.String:
        return v.String() == ""
    case reflect.Bool:
        return !v.Bool()
    case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface, reflect.Chan, reflect.Func:
        return v.IsNil()
    case reflect.Struct:
        // 可选:递归判断结构体是否全为零值(需谨慎,可能影响性能)
        // 此处按“非空结构体”视为非零(因无通用 DeepZero 判断),如需严格判断请另行实现
        return false
    case reflect.Float32, reflect.Float64:
        return v.Float() == 0.0
    default:
        return false
    }
}

配合结构体遍历,即可精准提取非空字段名:

Z Code
Z Code

智谱AI推出的轻量级AI代码编辑器

下载
package main

import (
    "fmt"
    "reflect"
)

type Users struct {
    Name     string
    Password string
    Age      int
    Token    *string
}

func isEmpty(v reflect.Value) bool {
    switch v.Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return v.Int() == 0
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
        return v.Uint() == 0
    case reflect.String:
        return v.String() == ""
    case reflect.Bool:
        return !v.Bool()
    case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface, reflect.Chan, reflect.Func:
        return v.IsNil()
    case reflect.Float32, reflect.Float64:
        return v.Float() == 0.0
    }
    return false
}

func getNonEmptyFieldNames(v interface{}) []string {
    val := reflect.ValueOf(v)
    if val.Kind() == reflect.Ptr {
        val = val.Elem()
    }
    if val.Kind() != reflect.Struct {
        panic("getNonEmptyFieldNames: input must be a struct or *struct")
    }

    var names []string
    typ := val.Type()
    for i := 0; i < val.NumField(); i++ {
        field := val.Field(i)
        if !isEmpty(field) {
            names = append(names, typ.Field(i).Name)
        }
    }
    return names
}

func main() {
    token := "abc123"
    u := Users{
        Name:     "Robert",  // non-empty
        Password: "",        // empty string → excluded
        Age:      0,         // zero int → excluded
        Token:    &token,    // non-nil pointer → included
    }

    fields := getNonEmptyFieldNames(u)
    fmt.Println(fields) // Output: [Name Token]
}

注意事项

  • 该方案基于反射,不适用于未导出(小写开头)字段,因 reflect 无法访问私有字段;
  • 对嵌套结构体(struct 类型字段),上述 isEmpty 默认返回 false(即视作“非空”),如需深度判空,需递归调用并结合 reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()),但性能开销显著;
  • 若结构体含指针字段(如 *string),IsNil() 能正确识别未初始化状态;但若指针指向零值(如 ptr := new(string); *ptr = ""),则 *ptr 为空字符串,此时需额外逻辑判断解引用后的值;
  • 生产环境高频调用时,建议缓存 reflect.Type 和字段信息,避免重复反射开销。

总结:通过自定义 isEmpty 辅助函数 + reflect 遍历,可安全、准确地筛选出结构体中真正携带有效数据的字段名,是构建灵活数据处理管道的关键技巧。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

401

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

528

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

306

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

72

2025.09.10

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

311

2023.08.02

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

246

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

204

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1431

2023.10.24

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号