亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

設計 Go 程序以避免循環依賴

設計 Go 程序以避免循環依賴

Go
眼眸繁星 2023-06-01 16:28:39
我是 Golang 的新手,我做了一個學習它的例子,但是我的例子中不允許導入周期,所以有人知道如何避免這種情況嗎?這是我的代碼。銀行,去package Bankimport (    "../../class/human"    "fmt")func Transfer(payer, receiver *human.Human, payment float64) {    if payer.Bank > payment {        payer.Bank -= payment        receiver.Bank += payment    } else {        fmt.Println("Bank balance not enough")    }}人間圍棋package human// import "../../func/Bank"type Human struct {    Name string    Cash float64    Bank float64}func (h *Human) Transfer(Receiver Human, payment float64) {}主程序package mainimport (    "./class/human"    "./func/Bank")func main() {    gary := human.Human{"Gary", 2000.0, 40000.0}    Sam := human.Human{"Sam", 10000.0, 500000.0}    Bank.Transfer(&Sam, &gary, 5000)}在上面的代碼中可以正常使用Bank.Transfer(&Sam, &gary, 5000)但我認為應該是人類使用 Bank 函數,所以我如何將它重寫成這個?Sam.Transfer(&gary, 5000)我試圖在 Human.go 中導入 Bank.go,但出現了導入周期不允許的錯誤。我不確定是我的邏輯錯誤還是我糟糕的代碼設計,但讓我們看看是否有人可以解決這個問題。
查看完整描述

1 回答

?
DIEA

TA貢獻1820條經驗 獲得超2個贊

這似乎是一個關于如何設計項目中的數據結構和操作及其依賴關系的一般軟件工程問題。

正如您所發現的,循環導入是不好的。有很多方法可以改變設計來解耦事物。一個是清晰的層——例如,Bank應該依賴Human而不是相反。但是,如果您想提供方便的功能來將錢從 轉移HumanHuman,您可以做的一件事是定義一個Bank對象將實現的接口。

然而,為簡單起見,我建議嚴格分層。沒有真正的理由 aHuman應該依賴于 a?Bank。在極限情況下,這可能會變得太麻煩,因為Humans 需要更多服務(你會依賴HumanaBus來讓Buses 移動Humans 嗎?)


為了回答評論和更新的問題,我會保持簡單:

package main


import (

? ? "fmt"

? ? "log"

)


type Human struct {

? ? ID? ?int64

? ? Name string

}


type Account struct {

? ? ID int64


? ? // Note: floats aren't great for representing money as they can lose precision

? ? // in some cases. Keeping this for consistency with original.

? ? Cash float64


? ? DaysSinceActive int64

}


type Bank struct {

? ? Accounts map[int64]Account

}


// Not checking negatives, etc. Don't use this for real banking :-)

func (bank *Bank) Transfer(src int64, dest int64, sum float64) error {

? ? srcAcct, ok := bank.Accounts[src]

? ? if !ok {

? ? ? ? return fmt.Errorf("source account %d not found", src)

? ? }

? ? destAcct, ok := bank.Accounts[dest]

? ? if !ok {

? ? ? ? return fmt.Errorf("destination account %d not found", dest)

? ? }

? ? // bank.Accounts[src] fetches a copy of the struct, so we have to assign it

? ? // back after modifying it.

? ? srcAcct.Cash -= sum

? ? bank.Accounts[src] = srcAcct

? ? destAcct.Cash += sum

? ? bank.Accounts[dest] = destAcct

? ? return nil

}


func main() {

? ? gary := Human{19928, "Gary"}

? ? sam := Human{99555, "Sam"}


? ? bank := Bank{Accounts: map[int64]Account{}}

? ? bank.Accounts[gary.ID] = Account{gary.ID, 250.0, 10}

? ? bank.Accounts[sam.ID] = Account{sam.ID, 175.0, 5}


? ? fmt.Println("before transfer", bank)


? ? if err := bank.Transfer(gary.ID, sam.ID, 25.0); err != nil {

? ? ? ? log.Fatal(err)

? ? }


? ? fmt.Println("after transfer", bank)

}

這段代碼使用了松散耦合。銀行需要知道的關于一個人的所有信息就是他們的 ID(可以是 SSN 或根據姓名、出生日期和其他內容計算出來的東西)來唯一地識別他們。人類應該持有銀行(如果一個人在多家銀行都有賬戶怎么辦?)。銀行不應該持有人(如果賬戶屬于多個人、公司、虛擬實體怎么辦?)等等。這里不需要接口,如果確實需要,您可以安全地將每種數據類型放在它們自己的包中。


查看完整回答
反對 回復 2023-06-01
  • 1 回答
  • 0 關注
  • 165 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號