一六九、go使用泛型封装一个可以应用于任何字段的模糊匹配

需求

针对 json数据里的user_name进行模糊搜索,返回匹配的列

参考数据

json 复制代码
[
 {
                "id": 122,
                "name": "sgm_info40_b233 5.5_plus",
                "logo": "https://bj.bcebos.com/v1/iov-recom/car_default.png",
                "user_name": "张三",
                "user_id": "838024601",
                "status": 0,
                "product_no": "",
                "product_status": "",
                "sdk_id": "",
                "kernel_no": "1.0.1",
                "dumi_appid": "",
                "dumi_appname": "iov_sgm_b233_2021",
                "dumi_appversion": "5.5_plus",
                "create_time": "2024-09-11 10:52:18",
                "update_time": ""
            },
            {
                "id": 123,
                "name": "sgm_info40_b223 5.5",
                "logo": "https://bj.bcebos.com/v1/iov-recom/car_default.png",
                "user_name": "李四",
                "user_id": "838024601",
                "status": 0,
                "product_no": "",
                "product_status": "",
                "sdk_id": "",
                "kernel_no": "1.0.1",
                "dumi_appid": "",
                "dumi_appname": "iov_sgm_b223_2021",
                "dumi_appversion": "5.5",
                "create_time": "2024-09-11 10:55:18",
                "update_time": ""
            }
]

实现

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
	"strings"
)

type Data struct {
	ID            int    `json:"id"`
	Name          string `json:"name"`
	Logo          string `json:"logo"`
	UserName      string `json:"user_name"`
	UserID        string `json:"user_id"`
	Status        int    `json:"status"`
	ProductNo     string `json:"product_no"`
	ProductStatus string `json:"product_status"`
	SdkID         string `json:"sdk_id"`
	KernelNo      string `json:"kernel_no"`
	DumiAppID     string `json:"dumi_appid"`
	DumiAppName   string `json:"dumi_appname"`
	DumiAppVersion string `json:"dumi_appversion"`
	CreateTime    string `json:"create_time"`
	UpdateTime    string `json:"update_time"`
}

// FilterByField 根据字段进行模糊匹配
func FilterByField[T any](data []T, fieldName string, keyword string) []T {
	matched := make([]T, 0)

	for _, item := range data {
		// 获取结构体的反射值
		val := reflect.ValueOf(item)

		// 检查 val 是结构体类型,若 val 是指针需要先解引用
		if val.Kind() == reflect.Ptr {
			val = val.Elem()
		}
		// 获取字段值
		fieldVal := val.FieldByName(fieldName)
		if fieldVal.IsValid() && fieldVal.Kind() == reflect.String {
			// 如果字段是字符串类型,进行模糊匹配
			if strings.Contains(fieldVal.String(), keyword) {
				matched = append(matched, item)
			}
		}
	}

	return matched
}


func main() {
	jsonData := `[
		{
			"id": 97,
			"name": "sgm_info40_l233 7",
			"logo": "https://bj.bcebos.com/v1/iov-recom/car_default.png",
			"user_name": "张三",
			"user_id": "838024601",
			"status": 0,
			"product_no": "",
			"product_status": "",
			"sdk_id": "",
			"kernel_no": "1.0.1",
			"dumi_appid": "",
			"dumi_appname": "iov_sgm_info40_l233",
			"dumi_appversion": "7",
			"create_time": "2024-03-07 11:43:07",
			"update_time": ""
		},
		{
			"id": 98,
			"name": "sgm_info40_l232 1",
			"logo": "https://bj.bcebos.com/v1/iov-recom/car_default.png",
			"user_name": "李四",
			"user_id": "838024601",
			"status": 0,
			"product_no": "",
			"product_status": "",
			"sdk_id": "",
			"kernel_no": "1.0.1",
			"dumi_appid": "",
			"dumi_appname": "iov_sgm_info40_l232",
			"dumi_appversion": "1",
			"create_time": "2024-03-07 15:03:29",
			"update_time": ""
		},
		{
			"id": 110,
			"name": "sgm_info40_u458 5.5",
			"logo": "https://bj.bcebos.com/v1/iov-recom/car_default.png",
			"user_name": "王五",
			"user_id": "838024601",
			"status": 0,
			"product_no": "",
			"product_status": "",
			"sdk_id": "",
			"kernel_no": "1.0.1",
			"dumi_appid": "",
			"dumi_appname": "iov_sgm_info40_u458",
			"dumi_appversion": "5.5",
			"create_time": "2024-07-25 11:23:44",
			"update_time": ""
		},
		{
			"id": 111,
			"name": "sgm_info40_3582_hev 5.5",
			"logo": "https://bj.bcebos.com/v1/iov-recom/car_default.png",
			"user_name": "张三",
			"user_id": "838024601",
			"status": 0,
			"product_no": "",
			"product_status": "",
			"sdk_id": "",
			"kernel_no": "1.0.1",
			"dumi_appid": "",
			"dumi_appname": "iov_sgm_info40_3582_hev",
			"dumi_appversion": "5.5",
			"create_time": "2024-07-25 11:23:44",
			"update_time": ""
		}
	]`

	var data []Data
	err := json.Unmarshal([]byte(jsonData), &data)
	if err != nil {
		fmt.Println("Error parsing JSON:", err)
		return
	}

	// 模糊搜索 user_name 包含 "张"
	result := FilterByField(data, "UserName", "张")

	// 打印结果
	for _, item := range result {
		fmt.Printf("ID: %d, UserName: %s, Name: %s\n", item.ID, item.UserName, item.Name)
	}
}

输出结果

复制代码
ID: 97, UserName: 张三, Name: sgm_info40_l233 7
ID: 111, UserName: 张三, Name: sgm_info40_3582_hev 5.5

解释:

  1. 泛型函数 FilterByField:这是一个使用泛型的公共方法,接受一个任意类型的切片,并根据指定的字段名进行模糊匹配。这里使用了 reflect 包来动态获取字段的值。
  2. reflect.ValueOf(item):通过反射获取结构体的字段值。
  3. FieldByName(fieldName):根据字段名获取对应的字段值,并判断其类型是否为字符串。
  4. strings.Contains:对字段值进行模糊匹配。
  5. fieldVal.IsValid(): 判断通过反射获取的字段值是否有效。具体来说,IsValid() 返回一个布尔值,如果字段存在并且可访问,返回 true,否则返回 false。
  6. fieldVal.Kind(): 返回一个 reflect.Kind 值,用于表示通过反射获取到的值的基础类型。Kind() 是枚举类型,表示 Go 中的基本类型,例如 reflect.String, reflect.Int, reflect.Struct 等。使用 Kind() 可以检查字段的数据类型,然后根据类型执行不同的操作。
  7. val.Elem():检查 输入对象是结构体类型,若是指针需要通过Elem()先解引用。

优点:

泛型使得这个方法可以适用于任何结构体类型。

反射使得可以通过字段名动态访问字段。

相关推荐
zzzll11111 小时前
Spring Boot 实现数据脱敏:自定义注解 + Jackson 序列化器
java·spring boot·后端
2501_941875285 小时前
从配置中心到动态管理的互联网工程语法演进与多语言实践分享
开发语言·python
hfywmsj5 小时前
广州餐饮铺位招租决策模型:多因子选址系统设计
开发语言·人工智能·python·广州餐饮铺位招租
vx-Biye_Design5 小时前
SSM伴侣动物伴护星小程序06330-计算机课程设计、毕业设计
spring boot·后端·elasticsearch·小程序·架构·课程设计·idea
努力的lpp7 小时前
php反序列化一(大白话版)
开发语言·web安全·php·ctf·反序列化
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
菜鸟~noob2337 小时前
【电子战】第03篇:CFAR(恒虚警)处理【含matlab代码】
开发语言·matlab
面向Google编程7 小时前
Apache Iceberg Variant 类型:v3 半结构化数据不再「二选一」
大数据·后端
jason成都8 小时前
Spring WebFlux 适配达梦新方案|dm‑r2dbc:Netty 异步传输的实验性 R2DBC 驱动
java·后端·spring
泡海椒8 小时前
内置SPI函数库详解:JQuick-Java Builtin工具类实战用法
java·开发语言·python