概述
很多人(特別是新手)在寫(xiě) Go 語(yǔ)言代碼時(shí)經(jīng)常會(huì)問(wèn)一個(gè)問(wèn)題,那就是一個(gè)方法的接受者類(lèi)型到底應(yīng)該是值類(lèi)型還是指針類(lèi)型呢,Go 的 wiki 上對(duì)這點(diǎn)做了很好的解釋?zhuān)襾?lái)翻譯一下。
何時(shí)使用值類(lèi)型
1.如果接受者是一個(gè) map,func 或者 chan,使用值類(lèi)型(因?yàn)樗鼈儽旧砭褪且妙?lèi)型)。
2.如果接受者是一個(gè) slice,并且方法不執(zhí)行 reslice 操作,也不重新分配內(nèi)存給 slice,使用值類(lèi)型。
3.如果接受者是一個(gè)小的數(shù)組或者原生的值類(lèi)型結(jié)構(gòu)體類(lèi)型(比如 time.Time 類(lèi)型),而且沒(méi)有可修改的字段和指針,又或者接受者是一個(gè)簡(jiǎn)單地基本類(lèi)型像是 int 和 string,使用值類(lèi)型就好了。
一個(gè)值類(lèi)型的接受者可以減少一定數(shù)量的垃圾生成,如果一個(gè)值被傳入一個(gè)值類(lèi)型接受者的方法,一個(gè)棧上的拷貝會(huì)替代在堆上分配內(nèi)存(但不是保證一定成功),所以在沒(méi)搞明白代碼想干什么之前,別因?yàn)檫@個(gè)原因而選擇值類(lèi)型接受者。
何時(shí)使用指針類(lèi)型
1.如果方法需要修改接受者,接受者必須是指針類(lèi)型。
2.如果接受者是一個(gè)包含了 sync.Mutex 或者類(lèi)似同步字段的結(jié)構(gòu)體,接受者必須是指針,這樣可以避免拷貝。
3.如果接受者是一個(gè)大的結(jié)構(gòu)體或者數(shù)組,那么指針類(lèi)型接受者更有效率。(多大算大呢?假設(shè)把接受者的所有元素作為參數(shù)傳給方法,如果你覺(jué)得參數(shù)有點(diǎn)多,那么它就是大)。
4.從此方法中并發(fā)的調(diào)用函數(shù)和方法時(shí),接受者可以被修改嗎?一個(gè)值類(lèi)型的接受者當(dāng)方法調(diào)用時(shí)會(huì)創(chuàng)建一份拷貝,所以外部的修改不能作用到這個(gè)接受者上。如果修改必須被原始的接受者可見(jiàn),那么接受者必須是指針類(lèi)型。
5.如果接受者是一個(gè)結(jié)構(gòu)體,數(shù)組或者 slice,它們中任意一個(gè)元素是指針類(lèi)型而且可能被修改,建議使用指針類(lèi)型接受者,這樣會(huì)增加程序的可讀性
當(dāng)你看完這個(gè)還是有疑慮,還是不知道該使用哪種接受者,那么記住使用指針接受者。
關(guān)于接受者的命名
社區(qū)約定的接受者命名是類(lèi)型的一個(gè)或兩個(gè)字母的縮寫(xiě)(像 c 或者 cl 對(duì)于 Client)。不要使用泛指的名字像是 me,this 或者 self,也不要使用過(guò)度描述的名字,最后,如果你在一個(gè)地方使用了 c,那么就不要在別的地方使用 cl。
您可能感興趣的文章:- GO語(yǔ)言基本類(lèi)型分析
- GO語(yǔ)言類(lèi)型轉(zhuǎn)換和類(lèi)型斷言實(shí)例分析
- Go語(yǔ)言基礎(chǔ)知識(shí)總結(jié)(語(yǔ)法、變量、數(shù)值類(lèi)型、表達(dá)式、控制結(jié)構(gòu)等)
- GO語(yǔ)言基本數(shù)據(jù)類(lèi)型總結(jié)
- Go語(yǔ)言中的復(fù)合類(lèi)型詳細(xì)介紹
- 為什么Go語(yǔ)言把類(lèi)型聲明放在后面?
- Go語(yǔ)言基本的語(yǔ)法和內(nèi)置數(shù)據(jù)類(lèi)型初探
- Go語(yǔ)言中如何通過(guò)方法為類(lèi)型添加行為