1. 程式人生 > 實用技巧 >結構體和方法

結構體和方法

go面向物件

package main

import "fmt"

type  treeNode struct {
	value int
	left,right *treeNode
}

func createNode(value int) *treeNode{
	return &treeNode{value:value}
}

func (node treeNode) print()  {
	fmt.Println(node.value)
}

func (node treeNode) setValue(value int)  {
	node.value = value
}

func main() {

	var root treeNode

	root = treeNode{value:3}

	root.left = &treeNode{}
	root.right = &treeNode{5,nil,nil}
	root.right.left = new(treeNode)
	root.right.right = createNode(23)

	var demo treeNode
	demo.value = 1
	demo.print() 

	demo.setValue(20)
	demo.print()

}

定義了兩個函式setValue和print,他們與普通函式的區別是前面多了一個接收者,影響的是呼叫方式的不同,其它的與普通函式並沒有卻別。如果是普通的定義方式,則定義和呼叫的方式如下:

func  print(node treeNode)  {
	fmt.Println(node.value)
}

func  setValue(node treeNode,value int) {
	node.value = value
}

print(demo)
setValue(demo,20)

值傳遞還是引用傳遞

上面傳遞的node是值傳遞,因為go函式裡都是值傳遞,執行結果如下

var demo treeNode
demo.value = 1
demo.print() //值1

demo.setValue(20)
demo.print()//值1

可以改成引用傳遞的方式,程式碼如下

package main

import "fmt"

type  treeNode struct {
	value int
	left,right *treeNode
}


func createNode(value int) *treeNode{
	return &treeNode{value:value}
}

func (node treeNode) print()  {
	fmt.Println(node.value)
}

func (node *treeNode) setValue(value int)  {  //與第一個程式碼塊的差別是這裡改成指標形式
	node.value = value
}


func main() {

	var root treeNode

	root = treeNode{value:3}

	root.left = &treeNode{}
	root.right = &treeNode{5,nil,nil}

	root.right.left = new(treeNode)

	root.right.right = createNode(23)

	var demo treeNode
	demo.value = 1
	demo.print() //不管接受者是值還是指標 都可以用demo呼叫

	demo.setValue(20) //這裡會自動將demo的指標傳遞
	demo.print()

}

總結

  1. 結構體擴充套件方法只是語法上的差別,與普通函式沒有差別,只是呼叫方法的差異
  2. 擴充套件預設是值傳遞,與普通函式保持一致,也可以是引用傳遞,不管是引用傳遞還是預設的值傳遞,在呼叫端都不受影響,直接拿結構體物件呼叫即可,編譯器很聰明,會自動的傳遞值和引用過去

何時使用值接受者和指標接受者

  1. 要改變內容,必須使用指標接受者
  2. 結構過大也考慮使用指標接受者
  3. 一致性:如果有指標接收者,最好都使用指標接受者