package main | |
import ( | |
"fmt" | |
) | |
const prompt = `Please enter number of operation: | |
1. Create new account | |
2. Show detail of account | |
3. Deposit | |
4. Withdraw | |
5. Make transfer | |
6. List exist accounts by Id | |
7. List exist accounts by balance | |
8. Delete account | |
9. Exit` | |
func main() { | |
fmt.Println("Welcome bank of xorm!") | |
Exit: | |
for { | |
fmt.Println(prompt) | |
var num int | |
fmt.Scanf("%d\n", &num) | |
switch num { | |
case 1: | |
fmt.Println("Please enter <name> <balance>:") | |
var name string | |
var balance float64 | |
fmt.Scanf("%s %f\n", &name, &balance) | |
if err := newAccount(name, balance); err != nil { | |
fmt.Println("Fail to create new account:", err) | |
} else { | |
fmt.Println("New account has been created") | |
} | |
case 2: | |
fmt.Println("Please enter <id>:") | |
var id int64 | |
fmt.Scanf("%d\n", &id) | |
a, err := getAccount(id) | |
if err != nil { | |
fmt.Println("Fail to get account:", err) | |
} else { | |
fmt.Printf("%#v\n", a) | |
} | |
case 3: | |
fmt.Println("Please enter <id> <deposit>:") | |
var id int64 | |
var deposit float64 | |
fmt.Scanf("%d %f\n", &id, &deposit) | |
a, err := makeDeposit(id, deposit) | |
if err != nil { | |
fmt.Println("Fail to deposit:", err) | |
} else { | |
fmt.Printf("%#v\n", a) | |
} | |
case 4: | |
fmt.Println("Please enter <id> <withdraw>:") | |
var id int64 | |
var withdraw float64 | |
fmt.Scanf("%d %f\n", &id, &withdraw) | |
a, err := makeWithdraw(id, withdraw) | |
if err != nil { | |
fmt.Println("Fail to withdraw:", err) | |
} else { | |
fmt.Printf("%#v\n", a) | |
} | |
case 5: | |
fmt.Println("Please enter <id> <balance> <id>:") | |
var id1, id2 int64 | |
var balance float64 | |
fmt.Scanf("%d %f %d\n", &id1, &balance, &id2) | |
if err := makeTransfer(id1, id2, balance); err != nil { | |
fmt.Println("Fail to transfer:", err) | |
} else { | |
fmt.Println("Transfer has been made") | |
} | |
case 6: | |
as, err := getAccountsAscId() | |
if err != nil { | |
fmt.Println("Fail to get accounts:", err) | |
} else { | |
for i, a := range as { | |
fmt.Printf("%d: %#v\n", i+1, a) | |
} | |
} | |
case 7: | |
as, err := getAccountsDescBalance() | |
if err != nil { | |
fmt.Println("Fail to get accounts:", err) | |
} else { | |
for i, a := range as { | |
fmt.Printf("%d: %#v\n", i+1, a) | |
} | |
} | |
case 8: | |
fmt.Println("Please enter <id>:") | |
var id int64 | |
fmt.Scanf("%d\n", &id) | |
if err := deleteAccount(id); err != nil { | |
fmt.Println("Fail to delete account:", err) | |
} else { | |
fmt.Println("Account has been deleted") | |
} | |
case 9: | |
fmt.Println("Thank you! Hope see you again soon!") | |
break Exit | |
default: | |
fmt.Println("Unknown operation number:", num) | |
} | |
fmt.Println() | |
} | |
} |
package main | |
import ( | |
"errors" | |
"log" | |
"github.com/go-xorm/xorm" | |
_ "github.com/mattn/go-sqlite3" | |
) | |
// Bank account | |
type Account struct { | |
Id int64 | |
Name string `xorm:"unique"` | |
Balance float64 | |
Version int `xorm:"version"` // Optimistic Locking | |
} | |
// ORM engine | |
var x *xorm.Engine | |
func init() { | |
// Create ORM engine and database | |
var err error | |
x, err = xorm.NewEngine("sqlite3", "./bank.db") | |
if err != nil { | |
log.Fatalf("Fail to create engine: %v\n", err) | |
} | |
// Sync tables | |
if err = x.Sync(new(Account)); err != nil { | |
log.Fatalf("Fail to sync database: %v\n", err) | |
} | |
} | |
func newAccount(name string, balance float64) error { | |
_, err := x.Insert(&Account{Name: name, Balance: balance}) | |
return err | |
} | |
func getAccount(id int64) (*Account, error) { | |
a := &Account{} | |
has, err := x.Id(id).Get(a) | |
if err != nil { | |
return nil, err | |
} else if !has { | |
return nil, errors.New("Account does not exist") | |
} | |
return a, nil | |
} | |
func makeDeposit(id int64, deposit float64) (*Account, error) { | |
a, err := getAccount(id) | |
if err != nil { | |
return nil, err | |
} | |
a.Balance += deposit | |
_, err = x.Update(a) | |
return a, err | |
} | |
func makeWithdraw(id int64, withdraw float64) (*Account, error) { | |
a, err := getAccount(id) | |
if err != nil { | |
return nil, err | |
} | |
if a.Balance < withdraw { | |
return nil, errors.New("Not enough balance") | |
} | |
a.Balance -= withdraw | |
_, err = x.Update(a) | |
return a, err | |
} | |
func makeTransfer(id1, id2 int64, balance float64) error { | |
a1, err := getAccount(id1) | |
if err != nil { | |
return err | |
} | |
a2, err := getAccount(id2) | |
if err != nil { | |
return err | |
} | |
if a1.Balance < balance { | |
return errors.New("Not enough balance") | |
} | |
a1.Balance -= balance | |
a2.Balance += balance | |
// Create Session object. | |
sess := x.NewSession() | |
defer sess.Close() | |
// Start transcation. | |
if err = sess.Begin(); err != nil { | |
return err | |
} | |
if _, err = sess.Update(a1); err != nil { | |
// Roll back when error occurs. | |
sess.Rollback() | |
return err | |
} else if _, err = sess.Update(a2); err != nil { | |
sess.Rollback() | |
return err | |
} | |
// Commit transcation. | |
return sess.Commit() | |
} | |
func getAccountsAscId() (as []Account, err error) { | |
// Find returns all results | |
err = x.Find(&as) | |
return as, err | |
} | |
func getAccountsDescBalance() (as []Account, err error) { | |
err = x.Desc("balance").Find(&as) | |
return as, err | |
} | |
func deleteAccount(id int64) error { | |
_, err := x.Delete(&Account{Id: id}) | |
return err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment