Я создал отображение объектов в Go, которое не является реляционным, это очень просто.Как я могу сделать это отображение объектов более сухим и многоразовым в 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?
'Не используйте общие имена, такие как« я »,« это »или« я », идентификаторы, типичные для объектно-ориентированных языков, которые уделяют больше внимания методам, а не функциям.' - https: // github. com/golang/go/wiki/CodeReviewComments # имя-получателя – OneOfOne