Skip to content

Instantly share code, notes, and snippets.

@unknwon
Last active August 29, 2015 14:00
Show Gist options
  • Save unknwon/03c4e9dec8ea97b3a010 to your computer and use it in GitHub Desktop.
Save unknwon/03c4e9dec8ea97b3a010 to your computer and use it in GitHub Desktop.
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")
}
// Following code should be improved by transactions
a1.Balance -= balance
a2.Balance += balance
if _, err = x.Update(a1); err != nil {
return err
} else if _, err = x.Update(a2); err != nil {
return err
}
return nil
}
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
}
@lunny
Copy link

lunny commented May 3, 2014

Excellent example!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment