I would question the framework design: the method is called "UpdateUser", so it should be executed in a transaction, so it should be a parameter of the service, and the transaction logic handled by the framework.
func (s \*Service) UpdateUser(ctx context.Context, tx models.Repo, userID string) error {
user, err := tx.GetUser(ctx, userID)
if err != nil {
return err
}
user.Name = "Updated"
return tx.SaveUser(ctx, user)
}In that instance, you are right, but there are often cases where you need to do multiple queries / updates spanning multiple tables in a single transaction, then you do need a generic transaction wrapper.