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()
}
总结
- 结构体扩展方法只是语法上的差别,与普通函数没有差别,是调用方法的差异,另外一个差异见https://tour.go-zh.org/methods/6
- 扩展默认是值传递,与普通函数保持一致,也可以是引用传递,不管是引用传递还是默认的值传递,在调用端都不受影响,直接拿结构体对象调用即可,编译器很聪明,会自动的传递值和引用过去
何时使用值接受者和指针接受者
- 要改变内容,必须使用指针接受者
- 结构过大也考虑使用指针接受者
- 一致性:如果有指针接收者,最好都使用指针接受者