|
I suppose the Go philosophy would discourage developers from tightly coupling Go types and their relational representations through an ORM. The idiomatic way of mapping your objects to a database is by defining a thin interface around a sql.DB, with first-class operations for your concrete types. type User struct {
ID int
Permalink string
}
type Storage sql.DB
Then you can either do func (s *Storage) WriteUser(user User) error {
if _, err := s.Exec(
"REPLACE INTO users VALUES (?, ?)",
user.ID,
user.Permalink,
); err != nil {
return fmt.Errorf("write user failed: %s", err)
}
return nil
}
or func (u User) Write(storage Storage) error {
if _, err := storage.Exec(
"REPLACE INTO users VALUES (?, ?)",
u.ID,
u.Permalink,
); err != nil {
return fmt.Errorf("write user failed: %s", err)
}
return nil
}
It's a bit more laborious in the sense of keystrokes, but it's also more explicit, which is, on balance and over the lifetime of a large software project, a good thing. |
It's a bit more laborious in the sense of keystrokes, but it's also more explicit, which is, on balance and over the lifetime of a large software project, a good thing.
OTOH, it feels like a high development cost to pay, relative to the alternatives out there. You certainly wouldn't use it for an MVP. Also, it would increase the opportunities to introduce bugs into the application (unless one actually feels they can write something better than, say ActiveRecord, from scratch).
I have a side-project in RoR that would benefit greatly from the performance boost provided by Go. However, the idea of writing all of the ORM functionality that ActiveRecord handles for me (not just managing of objects as you've shown, but the relationships between them) is quite daunting.