1. 程式人生 > 其它 >golang中的值方法和指標方法

golang中的值方法和指標方法

技術標籤:Go# Go知識點

和其他的面向物件程式語言有所區別,golang中並沒有直接提供物件語法,比如類似python, C++等中的class,而是以struct來間接實現面向物件程式設計
在給結構體物件新增方法的時候,接收者引數可以有兩種型別,一種是值引數,還有一種則是指標引數

func(receiver Type) Method
func(receiver *Type) Method
值物件可以呼叫值方法&指標方法
type Person struct{
	Name string 
	Age int 
}
// 值方法
func(p Person) SayHello()
{ fmt.Printf("Hello, my name is %s\n", p.Name) } // 引用方法 func(p *Person) SetAge(age int){ p.Age = age } func main(){ var jack = Person{"jack", 10} jack.SayHello() jack.SetAge(20) fmt.Println(jack.Age) // 20 }

很明顯,值型別肯定可以呼叫值方法,而對於指標方法的呼叫,其實是golang的語法糖,呼叫jack.SetAge的時候,會自動轉換成(&jack).SetAge

指標物件可以呼叫值方法&指標方法
type Person struct{
	Name string 
	Age int 
}
// 值方法
func(p Person) SayHello(){
	fmt.Printf("Hello, my name is %s\n", p.Name)
}
// 引用方法
func(p *Person) SetAge(age int){
	p.Age = age
}

func main(){
	var jack = &Person{"jack", 10}
	jack.SayHello()
	jack.SetAge
(20) fmt.Println(jack.Age) // 20 }

指標物件呼叫值方法也是golang中的語法糖,在呼叫值方法jack.SayHello的時候,會自動轉換成(*jack).SayHello


如果我們呼叫一個接口裡面的函式,結構體物件實現介面時的方法可能是指標方法也可以是值方法,那麼需要注意:

  • 值型別只能呼叫值方法
  • 指標型別可以呼叫值方法和指標方法

下面的例子說明了這個問題

package main 

import (
	"fmt"
)
// 介面型別
type Human interface{
	SayHello()
	SetAge(age int)
	GetAge()int 
}
// 結構體物件
type Person struct{
	Name string 
	Age int 
}
// 值方法
func(p Person) SayHello(){
	fmt.Printf("Hello, my name is %s\n", p.Name)
}
// 指標方法
func(p *Person) SetAge(age int){
	p.Age = age
}
// 值方法
func(p Person)GetAge()int{
	return p.Age
}

func main(){
	// jack是個介面,被一個指標物件賦值,下面的方法都可以正確執行
	var jack Human  // 宣告一個介面型別的物件
	jack = &Person{"jack", 10} // Person實現了介面
	jack.SayHello() 
	jack.SetAge(20)
	fmt.Println(jack.GetAge())

	// 值型別並沒有實現SetAge的方法,所以賦值的時候會報錯
	// cannot use Person literal (type Person) as type Human in assignment:
    //    Person does not implement Human (SetAge method has pointer receiver)
	var Tom Human 
	Tom = Person{"Tom", 12}
	Tom.SayHello()
	Tom.SetAge(10)
	fmt.Println(Tom.GetAge())
}

那麼什麼時候使用指標方法,什麼時候使用值方法呢,可以考慮:

  • 太多的指標可能會增加垃圾回收器的負擔。
  • 如果一個值型別的尺寸太大,那麼值傳參的時候的複製成本將不可忽略。 指標型別都是小尺寸型別。
  • 在併發場合下,同時呼叫為值方法和指標方法比較易於產生資料競爭。
  • sync標準庫包中的型別的值不應該被複制,所以如果一個結構體型別內嵌了這些型別,則不應該為這個結構體型別宣告值方法。
  • 如果實在拿不定主意在一個方法宣告中應該使用值型別屬主還是指標型別屬主,那麼請使用指標方法