golang中的不可變類(lèi)型有哪些?可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)-專(zhuān)業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性?xún)r(jià)比平遙網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式平遙網(wǎng)站制作公司更省心,省錢(qián),快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋平遙地區(qū)。費(fèi)用合理售后完善,10余年實(shí)體公司更值得信賴(lài)。如何利用不變性來(lái)增強(qiáng)你的 Golang 應(yīng)用程序的可讀性和穩(wěn)定性
不變性的概念非常簡(jiǎn)單. 創(chuàng)建對(duì)象 (或結(jié)構(gòu)體) 后, 將永遠(yuǎn)無(wú)法更改它. 這是一成不變的. 盡管這個(gè)概念看起來(lái)很簡(jiǎn)單, 但使用它或從中受益并不那么容易.
正如計(jì)算機(jī)科學(xué) (和生活) 中的大多數(shù)事物一樣, 有許多種方法可以達(dá)到相同的結(jié)果, 就不變性而言, 兩者沒(méi)有什么不同. 您應(yīng)該把它看做是工具包中的一個(gè)工具, 并使用在適用的問(wèn)題場(chǎng)景上. 關(guān)于不變性的一個(gè)非常好的用例是在您進(jìn)行并發(fā)編程時(shí). Golang 在設(shè)計(jì)時(shí)就考慮了并發(fā)性, 因此在 go 中使用并發(fā)非常普遍.
無(wú)論您使用哪種范例都可以通過(guò)以下方法在 Golang 中使用一些不變性概念來(lái)使代碼更具可讀性和穩(wěn)定性.
這與封裝類(lèi)似. 使用非導(dǎo)出字段創(chuàng)建結(jié)構(gòu), 僅導(dǎo)出作用的函數(shù). 由于您只對(duì)那些結(jié)構(gòu)的行為感興趣, 因此該技術(shù)對(duì)接口非常有用. 這項(xiàng)技術(shù)的另一個(gè)很好的補(bǔ)充是將創(chuàng)建函數(shù) (或構(gòu)造函數(shù)) 添加并導(dǎo)出到您的結(jié)構(gòu)中. 這樣您可以確保該結(jié)構(gòu)的狀態(tài)始終有效. 始終保持有效狀態(tài)可以使代碼更加可靠, 因?yàn)槟槐乩^續(xù)處理要對(duì)該結(jié)構(gòu)進(jìn)行的每個(gè)操作的無(wú)效狀態(tài). 下面是一個(gè)非?;镜氖纠?
package amounts import "errors" type Amount struct { value int } func NewAmount(value int) (Amount, error) { if value < 0 { return Amount{}, errors.New("Invalid amount") } return Amount{value: value}, nil } func (a Amount) GetValue() int { return a.value }
在此程序包中, 我們定義了 Amount
類(lèi)型, 具有未導(dǎo)出的字段 value
, 構(gòu)造函數(shù) NewAmount
以及 GetValue
方法用于 Amount
類(lèi)型. 一旦 NewAmount
函數(shù)創(chuàng)建了 Amount
結(jié)構(gòu), 就無(wú)法更改它. 因此它從包的外部來(lái)說(shuō)是不可變的 (盡管在 go 2 中有 更改此內(nèi)容的建議, 但 go 1 中沒(méi)有創(chuàng)建不變結(jié)構(gòu)的方法). 此外沒(méi)有處于無(wú)效狀態(tài) (在這種情況下為負(fù)數(shù)) 的 Amount
類(lèi)型的變量, 因?yàn)閯?chuàng)建它們的唯一方法已經(jīng)對(duì)此進(jìn)行了驗(yàn)證. 我們可以從另一個(gè)包中調(diào)用它:
a, err := amounts.NewAmount(10) *// 處理錯(cuò)誤 *log.Println(a.GetValue())
最基本的概念是在創(chuàng)建一個(gè)對(duì)象(或者結(jié)構(gòu)體)后,再也不去改變它。但是我們經(jīng)常在實(shí)體狀態(tài)很重要的應(yīng)用上工作。不過(guò),程序中實(shí)體狀態(tài)和實(shí)體內(nèi)部表示是不同的。在使用不變性時(shí),我們?nèi)匀豢梢越o實(shí)體賦予多個(gè)狀態(tài)。這意味著已創(chuàng)建的結(jié)構(gòu)體不會(huì)改變,但是它的副本會(huì)改變。這并不意味著我們需要手動(dòng)實(shí)現(xiàn)復(fù)制結(jié)構(gòu)體中每個(gè)字段的功能。
相反地,當(dāng)調(diào)用函數(shù)時(shí)我們可以依賴(lài) Go 語(yǔ)言復(fù)制值的本機(jī)行為。對(duì)于任意一個(gè)會(huì)改變實(shí)體狀態(tài)的操作,我們可以創(chuàng)建一個(gè)用來(lái)接收結(jié)構(gòu)體作為參數(shù)(或者作為函數(shù)接收器)的函數(shù),在執(zhí)行完畢之后返回改變后的版本。這是一項(xiàng)非常強(qiáng)大的技術(shù),因?yàn)槟隳軌蚋淖兏北旧系娜魏蝺?nèi)容,而無(wú)需更改函數(shù)調(diào)用者作為參數(shù)傳遞的變量。這意味著沒(méi)有副作用和可預(yù)測(cè)的行為。如果相同的結(jié)構(gòu)體被傳遞給并發(fā)函數(shù),每個(gè)結(jié)構(gòu)體都會(huì)接收到它的副本,而不是指向它的指針。
當(dāng)你在使用切片功能時(shí),你會(huì)看到此行為應(yīng)用于 [append](https://golang.org/pkg/builtin/#append)
函數(shù)
回到我們的例子中,讓我們實(shí)現(xiàn) Account
類(lèi)型,它包含了Amount
類(lèi)型的 balance
字段。同時(shí),我們添加 Deposit
和 Withdraw
方法來(lái)改變 Account
實(shí)體的狀態(tài)。
package accounts import ( "errors" "my-package/amounts" ) type Account struct { balance amounts.Amount } func NewEmptyAccount() Account { amount, _ := amounts.NewAmount(0) return NewAccount(amount) } func NewAccount(amount amounts.Amount) Account { return Account{balance: amount} } func (acc Account) Deposit(amount amounts.Amount) Account { newAmount, _ := amounts.NewAmount(acc.balance.GetValue() + amount.GetValue()) acc.balance = newAmount return acc } func (acc Account) Withdraw(amount amounts.Amount) (Account, error) { newAmount, err := amounts.NewAmount(acc.balance.GetValue() - amount.GetValue()) if err != nil { return acc, errors.New("Insuficient funds") } acc.balance = newAmount return acc, nil }
如果你檢查我們創(chuàng)建的方法,他們會(huì)覺(jué)得我們事實(shí)上改變了作為函數(shù)接收器的 Account
結(jié)構(gòu)的狀態(tài)。由于我們沒(méi)有使用指針,情況并非如此,由于結(jié)構(gòu)體的副本作為這些函數(shù)的接收器來(lái)傳遞,我們將更改只在函數(shù)作用域內(nèi)有效的副本,然后返回它。這是在另一個(gè)包中調(diào)用它的示例:
a, err := amounts.NewAmount(10) acc := accounts.NewEmptyAccount() acc2 := acc.Deposit(a) log.Println(acc.GetBalance()) log.Println(acc2.GetBalance())
命令行上的結(jié)果會(huì)是這樣的:
2020/06/03 22:22:40 {0} 2020/06/03 22:22:40 {10}
如你所見(jiàn),盡管通過(guò)變量 acc
調(diào)用了 Deposit
方法,但實(shí)際上變量并沒(méi)有改變,它返回了新的 Account
副本(分配給 acc2
),其包含了改變后的字段。
使用指針具有優(yōu)于復(fù)制值的優(yōu)點(diǎn),特別是如果您的結(jié)構(gòu)很大時(shí),在復(fù)制時(shí)可能會(huì)導(dǎo)致性能問(wèn)題,但是您應(yīng)始終問(wèn)自己是否值得,不要嘗試過(guò)早地優(yōu)化代碼。尤其是在使用并發(fā)時(shí)。您可能會(huì)在一些糟糕的情況下結(jié)束。
不變性不僅可以應(yīng)用于結(jié)構(gòu),還可以應(yīng)用于函數(shù)。如果我們用相同的參數(shù)兩次執(zhí)行相同的函數(shù),我們應(yīng)該收到相同的結(jié)果,對(duì)嗎?好吧,如果我們依賴(lài)于外部狀態(tài)或全局變量,則可能并非總是如此。最好避免這種情況。有幾種方法可以實(shí)現(xiàn)這一目標(biāo)。
如果您在函數(shù)內(nèi)部使用共享的全局變量,請(qǐng)考慮將該值作為參數(shù)傳遞,而不是直接在函數(shù)內(nèi)部使用。 那會(huì)使您的函數(shù)更可預(yù)測(cè),也更易于測(cè)試。整個(gè)代碼的可讀性也會(huì)更容易,其他人也將會(huì)了解到值可能會(huì)影響函數(shù)行為,因?yàn)樗且粋€(gè)參數(shù),而這就是參數(shù)的用途。 這里有一個(gè)例子:
package main import ( "fmt" "time" ) var rand int = 0 func main() { rand = time.Now().Second() + 1 fmt.Println(sum(1, 2)) } func sum(a, b int) int { return a + b + rand }
這個(gè)函數(shù) sum
使用全局變量作為自己計(jì)算的一部分。 從函數(shù)簽名來(lái)看這不是很清楚。 更好的方法是將rand變量作為參數(shù)傳遞。 因此該函數(shù)看起來(lái)應(yīng)該像這樣:
func sum(a, b, rand **int**) **int** { return a + b + rand }
看完上述內(nèi)容,你們對(duì)golang中的不可變類(lèi)型有進(jìn)一步的了解嗎?如果還想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,感謝各位的閱讀。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線(xiàn),公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。
當(dāng)前題目:golang中的不可變類(lèi)型有哪些-創(chuàng)新互聯(lián)
分享地址:http://jinyejixie.com/article34/pejse.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、用戶(hù)體驗(yàn)、服務(wù)器托管、電子商務(wù)、全網(wǎng)營(yíng)銷(xiāo)推廣、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容