练习 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
最后修改日期: 2022年8月29日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。