一六九、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()先解引用。

优点:

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

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

相关推荐
David爱编程8 分钟前
Java 守护线程 vs 用户线程:一文彻底讲透区别与应用
java·后端
小奏技术25 分钟前
国内APP的隐私进步,从一个“营销授权”弹窗说起
后端·产品
小研说技术43 分钟前
Spring AI存储向量数据
后端
苏三的开发日记43 分钟前
jenkins部署ruoyi后台记录(jenkins与ruoyi后台处于同一台服务器)
后端
苏三的开发日记1 小时前
jenkins部署ruoyi后台记录(jenkins与ruoyi后台不在同一服务器)
后端
陈三一1 小时前
MyBatis OGNL 表达式避坑指南
后端·mybatis
whitepure1 小时前
万字详解JVM
java·jvm·后端
我崽不熬夜1 小时前
Java的条件语句与循环语句:如何高效编写你的程序逻辑?
java·后端·java ee
我崽不熬夜1 小时前
Java中的String、StringBuilder、StringBuffer:究竟该选哪个?
java·后端·java ee
文火冰糖的硅基工坊2 小时前
[激光原理与应用-317]:光学设计 - Solidworks - 草图
开发语言·python·信息可视化·系统架构