gpt4 book ai didi

go - 如何将嵌套结构中的字段设置为零值?

转载 作者:行者123 更新时间:2023-12-01 22:08:38 24 4
gpt4 key购买 nike

假设我有一个想要Thing1的struct json.Marshal实例

type Thing1 struct {
A string `json:"a,omitempty"`
B int `json:"b,omitempty"`
C Thing2 `json:"c,omitempty"`
}

type Thing2 struct {
D bool `json:"d,omitempty"`
E int `json:"e,omitempty"`
}

...

thing1 := Thing1{
A: "test",
B: 42,
C: Thing2{D: true, E: 43},
}

您将如何编写一个函数,该函数采用任何结构的实例和字段列表进行编辑,并返回传入对象的克隆(或仅进行突变),但将已编辑的字段设置为零值?
redact(thing1, []string{"B", "D"})
thing1 == Thing1{
A: "test",
B: 0,
C: Thing2{D: false, E: 43},
}

我不能将 json:"-"用作字段标记,因为我正在使用的查询语言(Dgraph)需要使用当前的标记。

编辑:不在示例中,但如果适用,还应删除数组中的对象

最佳答案

使用反射来操纵结构体字段的值。以下是我在评论中所写内容的概念验证。由于这只是一个问题,因此您可能需要调整/修改代码以符合您的需求。

此功能会更改原始数据。代码是不言自明的。

func redact(target interface{}, fieldsToModify []string) {
// if target is not pointer, then immediately return
// modifying struct's field requires addresable object
addrValue := reflect.ValueOf(target)
if addrValue.Kind() != reflect.Ptr {
return
}

// if target is not struct then immediatelly return
// this might need to be modified as per your needs
targetValue := addrValue.Elem()
targetType := targetValue.Type()
if targetType.Kind() != reflect.Struct {
return
}

// loop the fields
for i := 0; i < targetType.NumField(); i++ {
fType := targetType.Field(i)
fValue := targetValue.Field(i)

// if the field type is struct, then call redact() recursively
if fValue.Kind() == reflect.Struct {
redact(fValue.Addr().Interface(), fieldsToModify)
continue
}

// if the field is slice, loop then call redact() recursively
if fValue.Kind() == reflect.Array || fValue.Kind() == reflect.Slice {
for i := 0; i < fValue.Len(); i++ {
redact(fValue.Index(i).Addr().Interface(), fieldsToModify)
}
continue
}

// loop the fieldsToModify
for _, fieldToModify := range fieldsToModify {
if fieldToModify == fType.Name && fValue.CanSet() {
fValue.Set(reflect.Zero(fType.Type))
}
}
}
}

第一个参数中的 redact()函数指针数据,因为修改字段需要addresable对象。
type Thing2 struct {
D bool `json:"d,omitempty"`
E int `json:"e,omitempty"`
}

type Thing1 struct {
A string `json:"a,omitempty"`
B int `json:"b,omitempty"`
C Thing2 `json:"c,omitempty"`
H []Thing2 `json:"h,omitempty"`
}

thing1 := Thing1{
A: "test",
B: 42,
C: Thing2{D: true, E: 43},
H: []Thing2{Thing2{D: true, E: 43}},
}

fmt.Printf("before: %#v \n", thing1)
// before: main.Thing1{A:"test", B:42, C:main.Thing2{D:true, E:43}, H:[]main.Thing2{main.Thing2{D:true, E:43}}}

redact(&thing1, []string{"B", "D"})
fmt.Printf("after: %#v \n", thing1)
// after: main.Thing1{A:"test", B:0, C:main.Thing2{D:false, E:43}, H:[]main.Thing2{main.Thing2{D:false, E:43}}}

游乐场: https://play.golang.org/p/wy39DGdSVV7

关于go - 如何将嵌套结构中的字段设置为零值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59402381/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com