2017-05-11 56 views
1

我有一個結構:如果在結構golang中值爲零,爲0,則更新字段?

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具有零一些屬性(字符串),假(布爾),0(INT),... 我要檢查,如果B的場未分配的值,該字段將接收所述的相同字段的值,

例如:

B的關於字段是零;

A的關於字段是「我是管理員」 我想B的關於字段是「我是管理員」。

我可以編寫代碼:

if len(B.About) == 0 { 
    B.About = A.About 

} 到其他領域一樣,我不想檢查一步一步的所有領域。

+1

你可能想改一下你的問題。我讀了4次,我仍然不知道你的問題是什麼。 –

+0

我的問題已更新,非常感謝! –

+0

好吧,現在我明白了。這是可行的,通用的方式,但這將需要使用反射包。如果你的表現不是問題,那麼可以考慮。 –

回答

1
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} 
+0

非常感謝!如果我解決了我的問題,我會檢查你的代碼並投票。再次感謝! –

+0

歡迎您。我認爲代碼足以讓你理解,但如果我是你,我會仔細看看反射包。 –

+0

我愛你,你很熱心 –

-1

如果我正確理解你要完成什麼,你應該更好地使用指向對象的指針而不是對象。

例如,

A := &User{1,"admin", "I am a admin",status: 1,....} 
if A != nil { 
    fmt.Println(A) 
} else { 
    fmt.Println("nil object") 
} 

沒有理由以檢查對象的字段是默認值。

+0

對不起。只有幾個字段是默認值 –