练习 9.1: 给gopl.io/ch9/bank1程序添加一个Withdraw(amount int)取款函数。其返回结果应该要表明事务是成功了还是因为没有足够资金失败了。这条消息会被发送给monitor的goroutine,且消息需要包含取款的额度和一个新的channel,这个新channel会被monitor goroutine来把boolean结果发回给Withdraw。
package main
import (
"fmt"
"time"
)
var deposits = make(chan int)
var balances = make(chan int)
var withdrawStatus = make(chan bool)
var failAmounts = make(chan int)
func Deposit(amount int) {
deposits <- amount
}
func Balance() int {
return <-balances
}
func Withdraw(amount int) bool {
deposits <- -amount
ok := <-withdrawStatus
if !ok {
fmt.Printf("%d$ 取款失败\n", amount)
}
return ok
}
func FailAmount() int {
return <-failAmounts
}
func teller() {
var balance int
var failAmount int
for {
select {
case amount := <-deposits:
if amount >= 0 {
balance += amount
} else {
if balance+amount >= 0 {
balance += amount
withdrawStatus <- true
} else {
failAmount += amount
withdrawStatus <- false
}
}
// 在此阻塞,直至接收者出现,才会吐出balance的值
case balances <- balance:
case failAmounts <- failAmount:
}
}
}
var money int = 0
func DepositPlain(amount int) {
money += amount
}
func BalancePlain() int {
return money
}
func main() {
go teller()
for i := 0; i < 10000; i++ {
go Deposit(10)
go Withdraw(10)
}
go func() { fmt.Println(Balance()) }()
time.Sleep(time.Second * 1)
fmt.Println("serial blinding", Balance(), "fail amount:", FailAmount())
close(deposits)
for i := 0; i < 10000; i++ {
go DepositPlain(10)
}
go func() { fmt.Println(BalancePlain()) }()
time.Sleep(time.Second * 1)
fmt.Println("plain", BalancePlain())
}
输出
C:\Users\Zhao-hangtian\AppData\Local\Temp\GoLand\___go_build_bank_go.exe
10$ 取款失败
10$ 取款失败
10$ 取款失败
10$ 取款失败
10$ 取款失败
10$ 取款失败
10$ 取款失败
80
serial blinding 70 fail amount: -70
95490
plain 95490
Process finished with the exit code 0
留言