The sample block below is what we can have without any language updates. I 
will let you decide your thoughts about its readability, but please note 
that even the error strings are built automatically—error propagation with 
error traces, of course.  Deferred error handling seems to clarify certain 
things, like errors from a rollback in this case. The full playground 
<https://go.dev/play/p/GHECrtFMFr->. (Please remember to try the automatic 
error traces when playing with it.)

func (db *Database) MoneyTransfer(from, to *Account, amount int) (err 
error) {
defer err2.Handle(&err)

tx := try.To1(db.BeginTransaction())
defer err2.Handle(&err, func() {
if errRoll := tx.Rollback(); errRoll != nil {
err = fmt.Errorf("%w: ROLLBACK ERROR: %w", err, errRoll)
}
})

try.To(from.RecerveBalance(tx, amount))

defer err2.Handle(&err, func() { // optional, following sample's wording
err = fmt.Errorf("cannot %w", err)
})

try.To(from.Withdraw(tx, amount))
try.To(to.Deposit(tx, amount))
try.To(tx.Commit())

return nil
}

We have used the err2 package <https://github.com/lainio/err2> in 
production for business-critical systems for four years. And yes, I'm the 
author of the OSS package.

On Friday, June 30, 2023 at 8:04:01 AM UTC+3 Mike Schinkel wrote:


   
*func (db *Database) Transfer(from, to Account, amount int) (err error) {*  
   
*err = db.Begin()*     *when err != nil **goto noTrans*
     *if **from*
*.Balance() >= amount {*     
* goto noFunds*     *}*
     *err = **from*
*.Withdraw(amount)*     *when err != nil **goto **noWithdraw*
     
*err = to.Deposit(amount)*     *when err != nil **goto **no**Deposit*
     
*err = db.Commit()*     *when err != nil **goto **no**Commit*
     
*return nil*     
*:noCommit:*       
*db.Rollback()*       
*return fmt.Errorf("cannot commit; %w", err)*     
*:noDeposit:*       
*db.Rollback()*       
*return fmt.Errorf("cannot deposit; %w", err)*     
*:noWithdraw:*       
*db.Rollback()*       
*return fmt.Errorf("cannot withdraw; %w", err)*     
*:noTrans:*       
*db.Rollback()*       
*return fmt.Errorf("cannot begin transaction; %w", err)*     
*:noFunds:*       
*db.Rollback()*       *return errors.New("no funds")*
     *} *8. Using the example above, is there not a way to also annotate 
the error in a shared manner vs. having to have all the different handle 
labels and duplicated code?

-Mike

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/fadd6051-bb65-4625-b1b2-9e87c40bf328n%40googlegroups.com.

Reply via email to