溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Go通過不變性優(yōu)化程序的方法是什么

發(fā)布時(shí)間:2022-08-24 16:35:06 來源:億速云 閱讀:118 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Go通過不變性優(yōu)化程序的方法是什么”,在日常操作中,相信很多人在Go通過不變性優(yōu)化程序的方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Go通過不變性優(yōu)化程序的方法是什么”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

減少對(duì)全局或外部狀態(tài)的依賴

當(dāng)我們使用相同的參數(shù),執(zhí)行相同的函數(shù)兩次,我們的預(yù)期,應(yīng)該得到相同的結(jié)果。但是當(dāng)我們的函數(shù)中依賴外部狀態(tài)或全局變量時(shí),函數(shù)可能會(huì)輸出不同的結(jié)果。我們最好避免這種情況。

函數(shù)的參數(shù)總是給定的,那我們調(diào)用,總是可以返回相同的函數(shù)。如果您有一個(gè)共享全局變量用于函數(shù)內(nèi)部的某些內(nèi)容,請(qǐng)考慮將該變量作為參數(shù)傳遞,而不是直接函數(shù)內(nèi)部使用它。

這可以讓您的函數(shù)返回值更加可預(yù)測(cè),并且更加易于測(cè)試,整個(gè)代碼的可讀性也會(huì)得到提高,因?yàn)檎{(diào)用者會(huì)知道,哪些值會(huì)影響函數(shù)的行為,參數(shù)的作用不就是會(huì)影響返回值的嗎?

讓我們看一個(gè)例子。

package main
import (
   "fmt"
   "math/rand"
   "time"
)
var randNum int
func main() {
   s1 := rand.NewSource(time.Now().UnixNano())
   r1 := rand.New(s1)
   randNum = r1.Intn(100)
   fmt.Println(Add(1, 1))
}
func Add(a, b int) int {
   return a + b + randNum
}

Add 函數(shù)中使用了全局變量 randNum 作為計(jì)算的一部分,從函數(shù)簽名中并沒有體現(xiàn)這一點(diǎn)。更好的方法是,全局變量 randNum 應(yīng)該作為參數(shù)傳遞,如下所示。

func Add(a, b, randNum int) int {
   return a + b + randNum
}

這樣更具有可預(yù)測(cè)性,而且我們?nèi)绻枰薷娜雲(yún)?,影響的作用域也僅在 Add 函數(shù)中。

僅導(dǎo)出結(jié)構(gòu)體的函數(shù),而不是成員變量

我們知道,Go 結(jié)構(gòu)體中的成員變量,如果首字母為大寫,那么該成員變量對(duì)外可見(這是編譯器決定的)。回到我們的博客,僅導(dǎo)出結(jié)構(gòu)體函數(shù),而不是成員變量,目的是希望成員變量的數(shù)據(jù)被保護(hù),保證成員變量的有效的狀態(tài)!因?yàn)檫@可以讓您的代碼更加可靠,您不必維護(hù)每個(gè)修改該成員變量的操作,因?yàn)檫@些操作都將無效。

舉一個(gè)例子

ackage main
import (
	"fmt"
)
type AK47 struct {
	bullet int
}
func NewAK47(bullet int) AK47 {
	return AK47{bullet: bullet}
}
func (a AK47) GetBullet() int {
	return a.bullet
}
func (a AK47) SetBullet(bullet int) {
	a.bullet = bullet
}
func main() {
	ak47 := NewAK47(30)
	fmt.Println(ak47.GetBullet())
	ak47.SetBullet(20)
	fmt.Println(ak47.GetBullet())
}

我們定義了一個(gè)結(jié)構(gòu)體 AK47,這把槍有一個(gè)成員變量 bullet 子彈數(shù),它是非導(dǎo)出字段,我們還定義了一個(gè)構(gòu)造函數(shù) NewAK47 和一個(gè) GetBullet 函數(shù)。

一旦創(chuàng)建了 AK47,就無法更改它的成員變量 bullet 了。此時(shí)您可能會(huì)有疑惑,如果我們需要修改成員變量呢?別急,您可以試試下面的方法。

在函數(shù)中使用復(fù)制值,而不是使用指針

在上一個(gè)副標(biāo)題中,我們提到了一個(gè)概念,在創(chuàng)建結(jié)構(gòu)體后永遠(yuǎn)不要更改它。然而在實(shí)際中,我們經(jīng)常需要修改結(jié)構(gòu)體中的成員變量。

我們?cè)谑褂貌蛔冃缘耐瑫r(shí),仍然可以維護(hù)實(shí)例化結(jié)構(gòu)體的多個(gè)狀態(tài),這并不意味著我們打破了結(jié)構(gòu)體創(chuàng)建后不要更改它,我們更改的是它的副本,也就是復(fù)制后的結(jié)構(gòu)體。復(fù)制后的結(jié)構(gòu)體?難道我們需要去實(shí)現(xiàn)很多復(fù)制結(jié)構(gòu)體每個(gè)字段的函數(shù)嗎?

當(dāng)然不,我們可以利用 Go 的特性,在調(diào)用函數(shù)時(shí),入?yún)⑹菑?fù)制值的行為。對(duì)于需要修改結(jié)構(gòu)體中成員變量的操作,我們可以創(chuàng)建一個(gè)函數(shù),該函數(shù)接收結(jié)構(gòu)體為參數(shù),并且返回一個(gè)修改后的結(jié)構(gòu)體副本。

我們可以在不改變調(diào)用方結(jié)構(gòu)體的情況下,修改該副本的任何內(nèi)容,這意味著對(duì)于原結(jié)構(gòu)體沒有任何副作用,并且該結(jié)構(gòu)體的值仍然是可預(yù)測(cè)的。

不知道您有沒有用過 Go 標(biāo)準(zhǔn)庫(kù)的 Slice 切片,其中的 append 函數(shù)就使用了這個(gè)方法。讓我們接著用 AK47 來實(shí)現(xiàn)這個(gè)方法

代碼如下

package main
import (
	"fmt"
)
type AK47 struct {
	bullet int
}
func NewAK47(bullet int) AK47 {
	return AK47{bullet: bullet}
}
func (a AK47) GetBullet() int {
	return a.bullet
}
func (a AK47) AddBullet(ak47 AK47) AK47 {
	newAK47 := NewAK47(a.GetBullet() + ak47.GetBullet())
	return newAK47
}
func main() {
	ak47 := NewAK47(30)
	add := NewAK47(20)
	fmt.Println(ak47.GetBullet())
	ak47 = ak47.AddBullet(add)
	fmt.Println(ak47.GetBullet())
}

如您所見,我們通過 AddBullet 函數(shù)增加槍的子彈,但實(shí)際上并沒有更改傳入的結(jié)構(gòu)體中的任何成員變量。最后,返回了一個(gè)帶有更新字段的新 AK47 結(jié)構(gòu)體。

與復(fù)制值相比,指針更有優(yōu)勢(shì),尤其是當(dāng)您的結(jié)構(gòu)體成員變量、內(nèi)容非常大時(shí)時(shí),這種方法,通過復(fù)制的方式修改數(shù)據(jù),可能會(huì)導(dǎo)致性能問題。

到此,關(guān)于“Go通過不變性優(yōu)化程序的方法是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

go
AI