【发布时间】:2016-02-07 22:47:20
【问题描述】:
我在 Go 中创建了一个非关系的对象映射,非常简单。
我有几个看起来像这样的结构:
type Message struct {
Id int64
Message string
ReplyTo sql.NullInt64 `db:"reply_to"`
FromId int64 `db:"from_id"`
ToId int64 `db:"to_id"`
IsActive bool `db:"is_active"`
SentTime int64 `db:"sent_time"`
IsViewed bool `db:"is_viewed"`
Method string `db:"-"`
AppendTo int64 `db:"-"`
}
要创建一条新消息,我只需运行此函数:
func New() *Message {
return &Message{
IsActive: true,
SentTime: time.Now().Unix(),
Method: "new",
}
}
然后我有一个用于这个结构的 message_crud.go 文件,如下所示:
要按唯一列(例如按 id)查找消息,我运行此函数:
func ByUnique(column string, value interface{}) (*Message, error) {
query := fmt.Sprintf(`
SELECT *
FROM message
WHERE %s = ?
LIMIT 1;
`, column)
message := &Message{}
err := sql.DB.QueryRowx(query, value).StructScan(message)
if err != nil {
return nil, err
}
return message, nil
}
为了保存消息(在数据库中插入或更新),我运行这个方法:
func (this *Message) save() error {
s := ""
if this.Id == 0 {
s = "INSERT INTO message SET %s;"
} else {
s = "UPDATE message SET %s WHERE id=:id;"
}
query := fmt.Sprintf(s, sql.PlaceholderPairs(this))
nstmt, err := sql.DB.PrepareNamed(query)
if err != nil {
return err
}
res, err := nstmt.Exec(*this)
if err != nil {
return err
}
if this.Id == 0 {
lastId, err := res.LastInsertId()
if err != nil {
return err
}
this.Id = lastId
}
return nil
}
sql.PlaceholderPairs() 函数如下所示:
func PlaceholderPairs(i interface{}) string {
s := ""
val := reflect.ValueOf(i).Elem()
count := val.NumField()
for i := 0; i < count; i++ {
typeField := val.Type().Field(i)
tag := typeField.Tag
fname := strings.ToLower(typeField.Name)
if fname == "id" {
continue
}
if t := tag.Get("db"); t == "-" {
continue
} else if t != "" {
s += t + "=:" + t
} else {
s += fname + "=:" + fname
}
s += ", "
}
s = s[:len(s)-2]
return s
}
但是每次我创建一个新结构时,例如一个用户结构,我必须复制粘贴上面的“crud section”并创建一个 user_crud.go 文件并将“消息”一词替换为“用户”,然后将这些词“消息”与“用户”。我重复了很多代码,它不是很干。有什么办法可以避免重复使用这些代码吗?我总是有一个 save() 方法,并且总是有一个函数 ByUnique() ,我可以在其中返回一个结构并按唯一列搜索。
在 PHP 中这很容易,因为 PHP 不是静态类型的。
这可以在 Go 中实现吗?
【问题讨论】:
-
Don't use generic names such as "me", "this" or "self", identifiers typical of object-oriented languages that place more emphasis on methods as opposed to functions.- github.com/golang/go/wiki/CodeReviewComments#receiver-names
标签: go