package main import ( "context" "database/sql" "fmt" "log" "github.com/cockroachdb/cockroach-go/crdb" ) func transferFunds(tx *sql.Tx, from int, to int, amount int) error { // Read the balance. var fromBalance int if err := tx.QueryRow( "SELECT balance FROM accounts WHERE id = $1", from).Scan(&fromBalance); err != nil { return err } if fromBalance < amount { return fmt.Errorf("insufficient funds") } // Perform the transfer. if _, err := tx.Exec( "UPDATE accounts SET balance = balance - $1 WHERE id = $2", amount, from); err != nil { return err } if _, err := tx.Exec( "UPDATE accounts SET balance = balance + $1 WHERE id = $2", amount, to); err != nil { return err } return nil } func main() { db, err := sql.Open("postgres", "postgresql://maxroach@localhost:26257/bank?ssl=true&sslmode=require&sslrootcert=certs/ca.crt&sslkey=certs/client.maxroach.key&sslcert=certs/client.maxroach.crt") if err != nil { log.Fatal("error connecting to the database: ", err) } defer db.Close() // Run a transfer in a transaction. err = crdb.ExecuteTx(context.Background(), db, nil, func(tx *sql.Tx) error { return transferFunds(tx, 1 /* from acct# */, 2 /* to acct# */, 100 /* amount */) }) if err == nil { fmt.Println("Success") } else { log.Fatal("error: ", err) } }