面试题答案
一键面试package main
import (
"fmt"
"reflect"
)
// 定义序列化结果的格式
type SerializedResult struct {
Fields map[string]interface{}
}
// 用于记录已经处理过的对象,避免循环引用
var visited = make(map[interface{}]bool)
func serialize(data interface{}) (SerializedResult, error) {
var result SerializedResult
result.Fields = make(map[string]interface{})
value := reflect.ValueOf(data)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
if value.Kind() != reflect.Struct {
return result, fmt.Errorf("unsupported type: %v", value.Kind())
}
if _, ok := visited[data]; ok {
return result, fmt.Errorf("circular reference detected")
}
visited[data] = true
defer delete(visited, data)
typeOf := value.Type()
for i := 0; i < value.NumField(); i++ {
field := value.Field(i)
tag := typeOf.Field(i).Tag.Get("serialize")
if tag != "" {
if field.Kind() == reflect.Struct {
subResult, err := serialize(field.Interface())
if err != nil {
return result, err
}
result.Fields[tag] = subResult.Fields
} else {
result.Fields[tag] = field.Interface()
}
}
}
return result, nil
}
你可以使用以下方式调用这个函数:
func main() {
type Person struct {
Name string `serialize:"person_name"`
Gender string `serialize:"person_gender"`
Friends []Person `serialize:"friends"`
}
p1 := Person{
Name: "Alice",
Gender: "Female",
Friends: []Person{},
}
p2 := Person{
Name: "Bob",
Gender: "Male",
Friends: []Person{p1},
}
p1.Friends = append(p1.Friends, p2)
result, err := serialize(p1)
if err != nil {
fmt.Println("Serialization error:", err)
return
}
fmt.Printf("Serialized result: %+v\n", result)
}
上述代码实现了以下功能:
serialize
函数接受一个interface{}
类型的参数,利用反射获取结构体的字段及其自定义标签。- 将结构体序列化为包含自定义标签和对应值的
SerializedResult
格式。 - 处理了结构体中的循环引用问题,通过
visited
map 来记录已经处理过的对象,如果检测到循环引用则返回错误。
在 main
函数中,定义了一个包含嵌套和循环引用的 Person
结构体,并调用 serialize
函数进行序列化。