为了账号安全,请及时绑定邮箱和手机立即绑定

避免反射 - 如何最好地重构此代码?

避免反射 - 如何最好地重构此代码?

Go
大话西游666 2021-11-29 16:57:42
我开始尝试使用 Go,到目前为止,它一直是一个爆炸。我决定做一个小应用程序来帮助朋友在他的(小)公司组织信息业务相关的信息,我想我会用Go来实现它。我还没有(完全)遇到问题,更多的是一个问题,我什么时候应该考虑使用反射?例如,我有 3 个相关类型:Company,Project和Staff. 它们都有几个共同的字段(例如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 的帖子后,我已经厌倦了进行反思:[反射是]一种强大的工具,除非绝对必要,否则应谨慎使用并避免使用。所以我的问题是,我应该使用反射吗,如果是这样,你能给我一些关于最好的技术的建议吗?这只是冰山一角,因为我觉得与这些类型相关的其余函数和方法似乎都是类似的重复(不要让我开始测试!)。
查看完整描述

1 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞

就像是:


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

}

请注意,我还没有编译此代码,但希望它足以给您一个想法。


几点建议:

  • 通读文档:https : //golang.org/pkg/database/sql/

  • sql.DB在程序启动时创建实例

  • 在 SQL 语句中显式指定列顺序 ( select full_name, history, .... from companies ....)


查看完整回答
反对 回复 2021-11-29
  • 1 回答
  • 0 关注
  • 145 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信