2015-12-22 49 views
1

我開始嘗試Go,到目前爲止它一直是一個爆炸。我決定製作一個小應用程序,它可以幫助朋友在他的(小)公司組織信息業務相關信息,我想我會用Go來實現它。避免反思 - 如何最好地重構此代碼?

我沒有(確切地說)遇到問題,這更多的是一個問題,我應該考慮什麼時候使用反射?例如,我有3種相關的類型:CompanyProjectStaff。他們都有幾個共同的領域(如id,name),你可以想象,從數據庫加載它們的功能(我使用的是MySQL)都非常相似。

LoadCompany()LoadStaff(),並且LoadProject()

// Loads the company from the database with the given id. 
func LoadCompany(id int) (Company, error) { 
    db := tools.OpenDB() 
    defer db.Close() 
    stmt, err := db.Prepare("SELECT * FROM companies WHERE id = ?") 
    if err != nil { 
     log.Panic(err) 
    } 
    var c Company 
    err = stmt.QueryRow(id).Scan(&c.id, &c.FullName, &c.Name, &c.History, &c.Overview, &c.Est, &c.Phone, &c.Website, &c.Email) 
    if err != nil { 
     return Company{}, err 
    } 
    return c, nil 
} 

// Loads the staff from the database with the given id. 
func LoadStaff(id int) (Staff, error) { 
    db := tools.OpenDB() 
    defer db.Close() 
    stmt, err := db.Prepare("SELECT * FROM staff WHERE id = ?") 
    if err != nil { 
     log.Panic(err) 
    } 
    var s Staff 
    err = stmt.QueryRow(id).Scan(&s.id, &s.FullName, &s.Name, &s.Email, &s.Joined, &s.Left, &s.History, &s.Phone, &s.Position) 
    if err != nil { 
     return Staff{}, err 
    } 
    return s, nil 
} 

// Loads the project from the database with the given id. 
func LoadProject(id int) (Project, error) { 
    db := tools.OpenDB() 
    defer db.Close() 
    stmt, err := db.Prepare("SELECT * FROM projects WHERE id = ?") 
    if err != nil { 
     log.Panic(err) 
    } 
    var p Project 
    err = stmt.QueryRow(id).Scan(&p.id, &p.Title, &p.Overview, &p.Value, &p.Started, &p.Finished, &p.Client, &p.Architect, &p.Status) 
    if err != nil { 
     return Project{}, err 
    } 
    return p, nil 
} 

當我寫LoadCompany(),我感覺我自己(啊哈作爲初級/中級程序員),因爲它似乎是最小的,乾淨的很不錯。但正如我寫的LoadStaff()LoadProject(),我所做的只是複製和調整。我敢肯定有一個更好的方式來做到這一點,但我厭倦跳進反思,讀Pike's post on it後:

[反射是一種強大的工具,應該小心使用和避免,除非絕對必要。

所以我的問題是,我應該使用反射,如果是的話,你能給我一些關於這種最好技術的指針嗎?這只是冰山一角,因爲我覺得其餘的與這些類型相關的函數和方法都是重複的(並且不會讓我開始測試!)。

謝謝!

+0

明確指定列順序看看https://github.com/jmoiron/sqlx。 – kostya

+0

謝謝......那應該解決掃描重複,關於3個函數和反射的一般建議嗎? –

回答

2

喜歡的東西:

func LoadObject(sql string, id int, dest ...interface{}) error { 
    db := tools.OpenDB() 
    defer db.Close() 
    stmt, err := db.Prepare(sql) 
    if err != nil { 
     log.Panic(err) 
    } 
    defer stmt.Close() 
    return stmt.QueryRow(id).Scan(dest) 
} 

// Loads the company from the database with the given id. 
func LoadCompany(id int) (c Company, err error) { 
    err = LoadObject("SELECT * FROM companies WHERE id = ?", &c.id, 
     &c.FullName, &c.Name, &c.History, &c.Overview, &c.Est, &c.Phone, &c.Website, &c.Email) 
    return 
} 

請注意,我還沒有編譯的代碼,但希望它是不夠好,給你一個想法。

幾點建議:

+0

是的,它幾乎完美。我所要做的就是返回行,因爲Scan()將dest視爲一系列項目中的第一個。謝謝! –