寫一篇好技術(shù)文章的經(jīng)驗秘籍,全在這兒了
619
2025-04-01
對不同類型的數(shù)據(jù)進(jìn)行分組
重要的是要記住,在 Go 中,沒有面向?qū)ο蟮母拍睿宰宇愋突蜃宇惖母拍钫娴牟淮嬖冢@些設(shè)計模式應(yīng)該被避免。 以下是不應(yīng)該遵循或?qū)嵤┑姆茨J剑?/p>
type Animal struct { Name string IsMammal bool}
動物類型被聲明為一個基礎(chǔ)類型,它試圖定義所有動物共有的數(shù)據(jù)。我也嘗試向動物提供一些常見的行為。
func (a *Animal) Speak() { fmt.Println("UGH!", "My name is", a.Name, ", it is", a.IsMammal, "I am a mammal")}
大多數(shù)動物都有以這種或那種方式說話的能力。然而,試圖將這種常見的行為僅僅適用于一種動物并沒有任何意義。在這一點上,我不知道這種動物發(fā)出什么聲音,所以我寫了 UGH
type Dog struct { Animal PackFactor int}
現(xiàn)在,真正的問題開始了。我試圖用嵌入的方式使狗擁有動物的一切,而且更多。從表面上看,這似乎是可行的,但也會有問題。既然如此,狗確實有一種特殊的說話方式
func (d *Dog) Speak() { fmt.Println("Woof!", "My name is", d.Name, ", it is", d.IsMammal, "I am a mammal with a pack factor of", d.PackFactor)}
在說話方法的實現(xiàn)中,我可以把 UGH 換成 Woof 。這就是 具體到狗的說話方式
type Cat struct { Animal ClimbFactor int}
如果我打算養(yǎng)一只代表動物的狗,那么我就必須養(yǎng)一只貓。使用嵌入法,貓是動物的一切,而且更多。
func (c *Cat) Speak() { fmt.Println("Meow!", "My name is", c.Name, ", it is", c.IsMammal, "I am a mammal with a climb factor of", c.ClimbFactor)}
在實現(xiàn) Speak 的方法中,我可以把 UGH 改成 Meow 。這就是具體到貓的說話方式 一切看起來都很好,看起來嵌入提供的功能與其他語言中的繼承相同。然后我試著把狗和貓分組,因為它們有共同的DNA,都是動物。
// This does not compile, a Dog and Cat are not an Animal.animals := []Animal{ Dog{ Animal: Animal{ Name: "Fido", IsMammal: true, }, PackFactor: 5, }, Cat{ Animal: Animal{ Name: "Milo", IsMammal: true, }, ClimbFactor: 4, },}for _, animal := range animals { animal.Speak()}
當(dāng)我嘗試這樣做時,編譯器抱怨狗和貓不是動物,這是真的。 嵌入與繼承不同,這是我需要遠(yuǎn)離的模式。 狗是狗,貓是貓,動物是動物。 我不能把狗和貓當(dāng)作動物來傳遞,因為它們不是。 這種機制也不是很靈活。 它需要開發(fā)人員進(jìn)行配置,除非我可以訪問代碼并且可以隨著時間的推移進(jìn)行配置更改,否則這不是很靈活 如果這不是我們構(gòu)建 Dog 和 Cat 集合的方式,我們?nèi)绾卧?Go 中做到這一點? 這不是通過共同的 DNA 進(jìn)行分組,而是通過共同的行為進(jìn)行分組。 行為是關(guān)鍵。
type Speaker interface { Speak()}
如果我使用一個接口,那么我可以定義我想要對不同類型的數(shù)據(jù)進(jìn)行分組的通用行為方法集:
speakers := []Speaker{ &Dog{ Animal: Animal{ Name: "Fido", IsMammal: true, }, PackFactor: 5, }, &Cat{ Animal: Animal{ Name: "Milo", IsMammal: true, }, ClimbFactor: 4, },}for _, speaker := range speakers { speaker.Speak()}
在新的代碼中,我現(xiàn)在可以根據(jù)狗和貓的共同行為集將它們分組。的行為,也就是狗和貓能說話的事實,把它們歸為一類。 事實上,Animal 類型確實是類型污染,因為聲明一個類型只是為了共享一組公共狀態(tài)是一種方式,應(yīng)該避免.
type Dog struct { Name string IsMammal bool PackFactor int}type Cat struct { Name string IsMammal bool ClimbFactor int}
在這種特殊情況下,我寧愿看到動物類型被刪除,字段被復(fù)制并粘貼到狗和貓類型中。稍后我將有關(guān)于更好的模式的說明,以消除這些情況的發(fā)生。 以下是原始代碼中的代碼異類:
Animal 類型提供了一個可重用狀態(tài)的抽象層。
程序永遠(yuǎn)不需要創(chuàng)建或單獨使用 Animal 類型的值。
泛化了 Animal 類型的 Speak 方法的實現(xiàn)。
永遠(yuǎn)不會調(diào)用 Animal 類型的 Speak 方法。
總結(jié)
關(guān)于聲明類型的指南:
聲明代表新事物或獨特事物的類型。
不要僅僅為了可讀性而創(chuàng)建別名。
驗證任何類型的值是單獨創(chuàng)建或使用的。
嵌入類型不是因為我需要狀態(tài),而是因為我們需要行為。
如果我不考慮行為,我就會將自己鎖定在未來不進(jìn)行級聯(lián)代碼更改就無法成長的設(shè)計中。
作為現(xiàn)有類型的別名或抽象的問題類型。
唯一目的是共享公共狀態(tài)的問題類型。
Go
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。