2016-04-24 36 views
0

我試着寫了一個簡單的ORM的MySQL,我有一個問題,如果定義的結構缺少一些領域:如何在Go中安全地檢測struct的清零值?

type User struct { 
    ID  int64 
    Username string 
    Password string 
    Email  string 
    Comment string 
} 

var u = User{Username: "user_0001", Password: "password"} 

用戶的某些字段沒有給出值,那麼它的價值將是一個歸零值,如字符串"",bool false,整數0等。

所以我用reflect獲得字段名稱和值,生成SQL插入一行。

INSERT INTO User (Id, Username, Password, Email, Comment) Values (0, "user_0001", "password", , ,)

你可以看到有有字符串的一些歸零值,如果我發現空字符串""和跳過它們,我可能會跳過正常價值。

回答

2

要處理的數據庫列,可能是NULL,您可以使用指針作爲街道Große弗里德里希建議,或使用在db包中的Null... -variants,例如sql.NullString

要使用空變體,該結構將

type User struct { 
    ID  int64 
    Username string 
    Password string 
    Email  sql.NullString 
    Comment sql.NullString 
} 

然後,您可以檢測值是通過檢查NullString.Valid設置。使用NullString的缺點是,你必須在打印或編組他們何時添加特殊情況,因爲它們沒有實現Stringer接口,也不MarshalJSONUnmarshalJSON。在設置字符串的值時,還必須手動設置NullString.Valid

例如,像

func TestNullString(t *testing.T) { 
    s := sql.NullString{} 
    t.Log(s) 

    s.String = "Test" 
    s.Valid = true 
    t.Log(s) 
} 

打印

null_string_test.go:21: { false} 
null_string_test.go:25: {Test true} 

測試要打印NullString你必須做的,而不是

func TestNullString(t *testing.T) { 
    s := sql.NullString{} 
    t.Log(s.String) 

    s.String = "Test" 
    s.Value = true 
    t.Log(s.String) 
} 

它打印:

null_string_test.go:21: 
null_string_test.go:25: Test 
1

您可以隨時在表格列中插入一個空字符串。如果知道零值之間的差異或完全不存在值是真的很重要,則需要使用指針。

type User struct { 
    ID  int64 
    Username *string 
} 

這將改變零值是nil這樣你就可以區分從""。 不利的一面是,這使得這種類型不易使用(nil檢查在實踐中經常被遺忘),你必須取消引用該字段才能得到實際的字符串。

在你的具體的例子,我不明白爲什麼你需要擔心空值的。難道你不能只將""插入到數據庫中,並在代碼中執行驗證(非空)而不是使用數據庫約束?

相關問題