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

假设我有一个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)需要当前的标签。


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


开心每一天1111
浏览 109回答 1
1回答

aluckdog

使用反射来操作结构字段的值。以下是我在评论中写的概念证明。由于这只是一个 poc,您可能需要调整/修改代码以满足您的需求。这个函数改变原始数据。代码是不言自明的。func redact(target interface{}, fieldsToModify []string) {&nbsp; &nbsp; // if target is not pointer, then immediately return&nbsp; &nbsp; // modifying struct's field requires addresable object&nbsp; &nbsp; addrValue := reflect.ValueOf(target)&nbsp; &nbsp; if addrValue.Kind() != reflect.Ptr {&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // if target is not struct then immediatelly return&nbsp; &nbsp; // this might need to be modified as per your needs&nbsp; &nbsp; targetValue := addrValue.Elem()&nbsp; &nbsp; targetType := targetValue.Type()&nbsp; &nbsp; if targetType.Kind() != reflect.Struct {&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // loop the fields&nbsp; &nbsp; for i := 0; i < targetType.NumField(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; fType := targetType.Field(i)&nbsp; &nbsp; &nbsp; &nbsp; fValue := targetValue.Field(i)&nbsp; &nbsp; &nbsp; &nbsp; // if the field type is struct, then call redact() recursively&nbsp; &nbsp; &nbsp; &nbsp; if fValue.Kind() == reflect.Struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; redact(fValue.Addr().Interface(), fieldsToModify)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // if the field is slice, loop then call redact() recursively&nbsp; &nbsp; &nbsp; &nbsp; if fValue.Kind() == reflect.Array || fValue.Kind() == reflect.Slice {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < fValue.Len(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; redact(fValue.Index(i).Addr().Interface(), fieldsToModify)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // loop the fieldsToModify&nbsp; &nbsp; &nbsp; &nbsp; for _, fieldToModify := range fieldsToModify {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if fieldToModify == fType.Name && fValue.CanSet() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fValue.Set(reflect.Zero(fType.Type))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}第一个参数中的redact()函数指针数据,因为修改字段需要可添加对象。type Thing2 struct {&nbsp; &nbsp; D bool `json:"d,omitempty"`&nbsp; &nbsp; E int&nbsp; `json:"e,omitempty"`}type Thing1 struct {&nbsp; &nbsp; A string&nbsp; &nbsp;`json:"a,omitempty"`&nbsp; &nbsp; B int&nbsp; &nbsp; &nbsp; `json:"b,omitempty"`&nbsp; &nbsp; C Thing2&nbsp; &nbsp;`json:"c,omitempty"`&nbsp; &nbsp; H []Thing2 `json:"h,omitempty"`}thing1 := Thing1{&nbsp; &nbsp; A: "test",&nbsp; &nbsp; B: 42,&nbsp; &nbsp; C: Thing2{D: true, E: 43},&nbsp; &nbsp; 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}}}&nbsp;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}}}&nbsp;游乐场: https: //play.golang.org/p/wy39DGdSVV7
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go