2020年4月16日 星期四

Go 小教室 - 如何檢驗 Go struct isEmpty




最近踩到一個 buffalo-pop ORM 的一個雷,範例如下:


type Job struct {
 ID             string         `json:"id" db:"id"`
 JobCreateType  JobCreateType  `json:"job_create_type" db:"job_create_type"`
 FileName       string         `json:"file_name" db:"file_name"`
 Status         JobStatus      `json:"status" db:"status"`
 CreatedAt      time.Time      `json:"created_at" db:"created_at"`
 UpdatedAt      time.Time      `json:"updated_at" db:"updated_at"`
 JobSourceInfo  *JobSourceInfo `json:"source_info" has_one:"job_source_infos" fk_id:"job_id"`
}

type JobSourceInfo struct {
 ID               string        `json:"id" db:"id"`
 JobID            string        `json:"job_id" db:"job_id"`
 SourceURL        string        `json:"source_url" db:"source_url"`
 }


一個 Job Struct 裡面有一個 Embedded Struct JobSourceInfo ,在資料庫裡面是 1 - 1 的關係,一開始產生 Job 時,並不預期一定會產生 JobScoureInfo,這時我們都會宣告為指標,理論上只要如下面範例,檢查是不是 nil 就能知道這個物件有沒被產生。

var ji *JobSourceInfo

if ji == nil {
    ji = new(JobSourceInfo)
    // do stuff 
}


但是.... Buffalo 的 ORM 的 Eager func 卻自作主張的幫我產生了一個 Empty Struct ,原本只需要檢查,指標是否為 nil ,但是現在卻得檢查是否為 empty Struct...

那讓我們來看看檢驗 Empty Struct 有幾種方法?


目前網路上看到有三種方法:

第一種:增加額外欄位


type JobSourceInfo struct {
 ready            bool          `json:"-"`
 ID               string        `json:"id" db:"id"`
 JobID            string        `json:"job_id" db:"job_id"`
 SourceURL        string        `json:"source_url" db:"source_url"`
}

使用的方法就是每次初始化時,去設定這個欄位為 true,如果沒有 default 就是 false,但是不夠簡潔和懶惰~


var ji JobSourceInfo

if !ji.ready {
    // do stuff 
}


第二種:檢測欄位中的空值


另一種也是懶人檢查法,就是直接檢查某個必填欄位是不是有值

var ji JobSourceInfo

if s.ID == "" {
    // do stuff 
}

講究一點,就再產生一個 isEmpty() 的 function


func (ji JobSourceInfo) isEmpty() bool {
    return s.ID == ""
}


第三種:直接跟 Empty Struct 比較 

雖然直觀,但是有點 tricky,而且醜醜的...

jobSourceInfo := &ampJobSourceInfo{}
if (JobSourceInfo{}) == *jobSourceInfo {
    
    // is empty do stuff
}


不知道各位有沒有更好的做法?


Reference:

沒有留言 :