Implement the Unit of Work pattern in Go by defining an interface for tracking changes and a concrete struct that manages a transactional context.
package repository
type UnitOfWork interface {
Commit() error
Rollback() error
Save(entity Entity) error
}
type unitOfWork struct {
db *sql.DB
tx *sql.Tx
changes []Entity
}
func NewUnitOfWork(db *sql.DB) UnitOfWork {
return &unitOfWork{db: db}
}
func (u *unitOfWork) Save(entity Entity) error {
u.changes = append(u.changes, entity)
return nil
}
func (u *unitOfWork) Commit() error {
if u.tx == nil {
var err error
u.tx, err = u.db.Begin()
if err != nil { return err }
}
for _, e := range u.changes {
if err := e.Save(u.tx); err != nil { return err }
}
return u.tx.Commit()
}
func (u *unitOfWork) Rollback() error {
if u.tx != nil { return u.tx.Rollback() }
return nil
}