go 语言动态返回所需字段
go
package main
import (
"encoding/json"
"errors"
"fmt"
"reflect"
)
func JsonPrint(student interface{}) interface{} {
jsonData, err := json.MarshalIndent(student, "", " ")
if err != nil {
fmt.Println("JSON 编码失败:", err)
return nil
}
return string(jsonData)
}
type Student struct {
AAA string
BBB string
CCC string
}
func main() {
// 传入返回值字符串
fields := []string{"CCC"}
// 创建切片数据集
student := []Student{
{AAA: "1", BBB: "John Doe", CCC: "20"},
{AAA: "2", BBB: "Jane Doe", CCC: "22"},
{AAA: "3", BBB: "Mike Smith", CCC: "23"},
}
data, _ := FormatConversion(student, fields)
fmt.Println("切片返回到前端的数据: ", data)
// 创建单个数据集
student2 := Student{
AAA: "John Doe",
BBB: "20",
CCC: "Male",
}
data2, _ := FormatConversion(student2, fields)
fmt.Println("结构体返回到前端的数据: ", data2)
}
// 不用看后面那两个函数,只需要调用这一个函数即可
// 这个函数引用了下面两个函数的逻辑
// 当前函数值用于判断传入的参数是结构体还是切片,然后执行后面对应的函数处理相关逻辑
func FormatConversion(base interface{}, fields []string) (interface{}, error) {
value := reflect.ValueOf(base)
switch value.Kind() {
case reflect.Struct:
// 传入参数为结构体,对切片进行处理
// 参数一为传入的结构体,参数二为所需要返回的字段
dynamicStruct, err := createDynamicStruct(base, fields)
if err != nil {
fmt.Println(err)
return nil, err
}
// 打印返回的数据
fmt.Println("打印转换后的数据" , JsonPrint(dynamicStruct))
return dynamicStruct, nil
case reflect.Slice:
// 传入参数为切片,对切片进行处理
// 参数一为传入的切片,参数二为所需要返回的字段
dynamicStruct, err := createDynamicStructsFromSlice(base, fields)
if err != nil {
fmt.Println(err)
return nil, err
}
// 打印转换后的数据
fmt.Println("打印转换后的数据" , JsonPrint(dynamicStruct))
return dynamicStruct, nil
default:
fmt.Println("未知类型") // 既不是结构体也不是切片
return nil, errors.New("参数一传入格式有误,请传入结构体或者切片")
}
}
// 传入一个结构体和字符串数组,返回一个动态结构体
// 同时在处理切片时也会用到该函数
func createDynamicStruct(base interface{}, fields []string) (interface{}, error) {
baseType := reflect.TypeOf(base)
if baseType.Kind() != reflect.Struct {
return nil, fmt.Errorf("expected a struct, got %s", baseType.Kind())
}
fieldValues := make([]reflect.Value, 0, len(fields))
fieldNames := make([]reflect.StructField, 0, len(fields))
for _, fieldName := range fields {
field, found := baseType.FieldByName(fieldName)
if !found {
return nil, fmt.Errorf("field %s not found in struct", fieldName)
}
fieldValues = append(fieldValues, reflect.ValueOf(base).FieldByName(fieldName))
fieldNames = append(fieldNames, reflect.StructField{
Name: fieldName,
Type: field.Type,
Tag: field.Tag,
})
}
// 创建一个动态类型,包含所需的字段
dynamicType := reflect.StructOf(fieldNames)
dynamicValue := reflect.New(dynamicType).Elem()
// 设置动态结构体的字段值
for i, fieldValue := range fieldValues {
dynamicValue.Field(i).Set(fieldValue)
}
return dynamicValue.Interface(), nil
}
// 传入一个切片和字符串数组,返回一个动态结构体切片
func createDynamicStructsFromSlice(baseSlice interface{}, fields []string) ([]interface{}, error) {
sliceValue := reflect.ValueOf(baseSlice)
if sliceValue.Kind() != reflect.Slice {
return nil, fmt.Errorf("expected a slice, got %s", sliceValue.Kind())
}
baseElemType := sliceValue.Type().Elem()
if baseElemType.Kind() != reflect.Struct {
return nil, fmt.Errorf("slice elements are not structs")
}
var dynamicSlice []interface{}
for i := 0; i < sliceValue.Len(); i++ {
elem := sliceValue.Index(i)
dynamicStruct, err := createDynamicStruct(elem.Interface(), fields)
if err != nil {
return nil, err
}
dynamicSlice = append(dynamicSlice, dynamicStruct)
}
return dynamicSlice, nil
}
上面代码可以直接放到main.go
运行一下,运行结果如下: