亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go通過不變性優(yōu)化程序詳解

 更新時間:2022年08月24日 14:53:46   作者:龔國瑋  
這篇文章主要為大家介紹了Go通過不變性優(yōu)化程序?qū)嵗斀?,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

不變性的概念非常簡單,在您創(chuàng)建結構體后,就永遠無法修改它。這個概念聽起來非常簡單,但您的程序想利用它從中收益并不是那么容易。接下來我們在 Go 中,使用不變性概念,來讓您的代碼更具有可讀性和穩(wěn)定性。

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

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

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

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

讓我們看一個例子。

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 作為計算的一部分,從函數(shù)簽名中并沒有體現(xiàn)這一點。更好的方法是,全局變量 randNum 應該作為參數(shù)傳遞,如下所示。

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

這樣更具有可預測性,而且我們?nèi)绻枰薷娜雲(yún)ⅲ绊懙淖饔糜蛞矁H在 Add 函數(shù)中。

僅導出結構體的函數(shù),而不是成員變量

我們知道,Go 結構體中的成員變量,如果首字母為大寫,那么該成員變量對外可見(這是編譯器決定的)?;氐轿覀兊牟┛?,僅導出結構體函數(shù),而不是成員變量,目的是希望成員變量的數(shù)據(jù)被保護,保證成員變量的有效的狀態(tài)!因為這可以讓您的代碼更加可靠,您不必維護每個修改該成員變量的操作,因為這些操作都將無效。

舉一個例子

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())
}

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

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

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

在上一個副標題中,我們提到了一個概念,在創(chuàng)建結構體后永遠不要更改它。然而在實際中,我們經(jīng)常需要修改結構體中的成員變量。

我們在使用不變性的同時,仍然可以維護實例化結構體的多個狀態(tài),這并不意味著我們打破了結構體創(chuàng)建后不要更改它,我們更改的是它的副本,也就是復制后的結構體。復制后的結構體?難道我們需要去實現(xiàn)很多復制結構體每個字段的函數(shù)嗎?

當然不,我們可以利用 Go 的特性,在調(diào)用函數(shù)時,入?yún)⑹菑椭浦档男袨?。對于需要修改結構體中成員變量的操作,我們可以創(chuàng)建一個函數(shù),該函數(shù)接收結構體為參數(shù),并且返回一個修改后的結構體副本。

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

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

代碼如下

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ù)增加槍的子彈,但實際上并沒有更改傳入的結構體中的任何成員變量。最后,返回了一個帶有更新字段的新 AK47 結構體。

與復制值相比,指針更有優(yōu)勢,尤其是當您的結構體成員變量、內(nèi)容非常大時時,這種方法,通過復制的方式修改數(shù)據(jù),可能會導致性能問題。您應該問自己,這么做是否值得,例如您正在編寫并發(fā)代碼?

總結

您在使用不變量時,請務必先權衡利弊。實現(xiàn)本篇博客中所描述的方法,需要大量的代碼。但是,如果我們在編寫并發(fā)代碼時,不考慮共享變量的不可變性,往往會出現(xiàn)與預期不符的情況,例如內(nèi)存競態(tài)問題?其實我想說的就是線程安全問題 : - )

實現(xiàn)不變性,也可能出現(xiàn)嚴重的性能問題!這是一把雙刃劍。請不要過早的優(yōu)化代碼。

以上就是Go通過不變性優(yōu)化程序詳解的詳細內(nèi)容,更多關于Go 程序不變性的資料請關注腳本之家其它相關文章!

相關文章

  • 淺析Go語言中Channel的各種用法

    淺析Go語言中Channel的各種用法

    這篇文章主要帶大家一起來學習一下Go語言中的if語句,也就是大家口中的判斷語句。文中的示例代碼講解詳細,對我們學習Go語言有一定幫助,需要的可以參考一下
    2022-11-11
  • 淺析goland等待鎖問題

    淺析goland等待鎖問題

    這篇文章主要介紹了goland等待鎖問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2020-11-11
  • 淺談Go切片的值修改是否會覆蓋數(shù)組的值?

    淺談Go切片的值修改是否會覆蓋數(shù)組的值?

    本文主要介紹了淺談Go切片的值修改是否會覆蓋數(shù)組的值,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下?
    2022-02-02
  • Golang最大遞減數(shù)算法問題分析

    Golang最大遞減數(shù)算法問題分析

    這篇文章主要介紹了Golang最大遞減數(shù)算法問題分析,結合實例形式分析了Go語言數(shù)字遍歷與運算相關操作技巧,需要的朋友可以參考下
    2017-01-01
  • go語言使用Chromedp實現(xiàn)二維碼登陸教程示例源碼

    go語言使用Chromedp實現(xiàn)二維碼登陸教程示例源碼

    這篇文章主要為大家介紹了go語言使用Chromedp實現(xiàn)二維碼登陸示例源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-04-04
  • Go語言為什么很少使用數(shù)組原理解析

    Go語言為什么很少使用數(shù)組原理解析

    這篇文章主要為大家介紹了Go語言為什么很少使用數(shù)組原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Go語言實現(xiàn)一個簡單的并發(fā)聊天室的項目實戰(zhàn)

    Go語言實現(xiàn)一個簡單的并發(fā)聊天室的項目實戰(zhàn)

    本文主要介紹了Go語言實現(xiàn)一個簡單的并發(fā)聊天室的項目實戰(zhàn),文中根據(jù)實例編碼詳細介紹的十分詳盡,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • RoaringBitmap原理及在Go中的使用詳解

    RoaringBitmap原理及在Go中的使用詳解

    這篇文章主要為大家介紹了RoaringBitmap原理及在Go中的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • 詳解golang碎片整理之 fmt.Scan

    詳解golang碎片整理之 fmt.Scan

    本文介紹了從golang語言中fmt包從標準輸入獲取數(shù)據(jù)的Scan系列函數(shù)、從io.Reader中獲取數(shù)據(jù)的Fscan系列函數(shù)以及從字符串中獲取數(shù)據(jù)的Sscan系列函數(shù)的用法,感興趣的小伙伴們可以參考一下
    2019-05-05
  • golang websocket 服務端的實現(xiàn)

    golang websocket 服務端的實現(xiàn)

    這篇文章主要介紹了golang websocket 服務端的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09

最新評論