Last active
August 29, 2015 14:00
-
-
Save unknwon/03c4e9dec8ea97b3a010 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Excellent example!