我有一个结构:
type User struct { ID int `json:"id"` Username string `json:"username"` About string `json:"about"` IsAdmin bool `json:"is_admin"` Status int `json:"status"` ...... } A:= User{1,"admin", "I am a admin",status: 1,....} B:= User{ID:1, Username: "UserBBBB"} ...enter code here... B is {1, "UserBBBB", "I am a admin", 1, ...(same value in A)}
对象B具有一些属性,分别为nil(字符串),false(布尔),0(整数),…。我想检查B的字段是否为未分配值,该字段将接收A中相同字段的值,
例:
B的关于字段为零;
A的“关于”字段是“我是管理员”。B的“关于”字段是“我是管理员”。
我可以写代码:
if len(B.About) == 0 { B.About = A.About
与其他字段类似,我不想逐步检查所有字段。
package main import ( "errors" "fmt" "log" "reflect" "time" ) type User struct { ID int `json:"id"` Username string `json:"username"` About string `json:"about"` IsAdmin bool `json:"is_admin"` Status int `json:"status"` Date *time.Time } func main() { now := time.Now() ua := User{ ID: 1, Username: "admin", About: "I am an admin", IsAdmin: true, Status: 1, Date: &now, } ub := User{ Username: "user", } fmt.Printf("ua: %+v\n", ua) fmt.Printf("ub: %+v\n", ub) err := Replace(ua, &ub) if err != nil { log.Fatal(err) } fmt.Printf("\nua: %+v\n", ua) fmt.Printf("ub: %+v\n", ub) } // IsZeroOfUnderlyingType return wether x is the is // the zero-value of its underlying type. func IsZeroOfUnderlyingType(x interface{}) bool { return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface()) } // Replace replaces all fields of struct b that have a // zero-value with the corresponding field value from a. // b must be a pointer to a struct. func Replace(a, b interface{}) error { // Check a. va := reflect.ValueOf(a) if va.Kind() != reflect.Struct { return errors.New("a is not a struct") } // Check b. vb := reflect.ValueOf(b) if vb.Kind() != reflect.Ptr { return errors.New("b is not a pointer") } // vb is a pointer, indirect it to get the // underlying value, and make sure it is a struct. vb = vb.Elem() if vb.Kind() != reflect.Struct { return errors.New("b is not a struct") } for i := 0; i < vb.NumField(); i++ { field := vb.Field(i) if field.CanInterface() && IsZeroOfUnderlyingType(field.Interface()) { // This field have a zero-value. // Search in a for a field with the same name. name := vb.Type().Field(i).Name fa := va.FieldByName(name) if fa.IsValid() { // Field with name was found in struct a, // assign its value to the field in b. if field.CanSet() { field.Set(fa) } } } } return nil }
输出量
ua: {ID:1 Username:admin About:I am an admin IsAdmin:true Status:1 Date:2017-05-11 17:47:30.805657327 +0200 CEST} ub: {ID:0 Username:user About: IsAdmin:false Status:0 Date:<nil>} ua: {ID:1 Username:admin About:I am an admin IsAdmin:true Status:1 Date:2017-05-11 17:47:30.805657327 +0200 CEST} ub: {ID:1 Username:user About:I am an admin IsAdmin:true Status:1 Date:2017-05-11 17:47:30.805657327 +0200 CEST}