在面向对象中,go语言仅支持封装,不支持继承和多态。
go语言中没有class,只有struct。
package main
import "fmt"
// struct(结构)的定义
type treeNode struct {
value int
left, right *treeNode
}
// 为结构定义构造函数(其实是一个工厂函数)
func createNode(value int) *treeNode {
return &treeNode{value: value} // 返回了局部变量的地址,这在go语言中是允许的
}
// 为结构定义方法
// 结构的方法需要在方法名前定义接收者
// 接收者可以是值接收者,也可以是指针接收者
// 方法print()的接收者(node treeNode)为值接收者
// 方法setValue()的接收者(node *treeNode)是指针接收者
// 因为值传递的关系,只有指针接收者才能改变结构内容,值接收者不能改变结构内容
func (node treeNode) print() {
fmt.Print(node.value)
}
func (node *treeNode) setValue(value int) {
// nil指针也可以作为指针接收者传入方法,但是取node.value会报错
if node == nil {
fmt.Println("Setting value to nil node. Ignored.")
return
}
node.value = value
}
// 遍历方法
func (node *treeNode) traverse() {
if node == nil {
return
}
node.left.traverse()
node.print()
node.right.traverse()
}
func main() {
var root treeNode
fmt.Println(root) // {0 <nil> <nil>}
// struct(结构)的创建
root = treeNode{value: 3}
root.left = &treeNode{}
root.right = &treeNode{5, nil, nil}
// 不论地址还是结构本身,一律使用.来访问成员
root.right.left = new(treeNode)
nodes := []treeNode {
{value: 3},
{},
{6, nil, &root},
}
fmt.Println(nodes) // [{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc42000a060}]
root.left.right = createNode(2)
// 值接收者接收值:拷贝值给值接收者
root.print() // 3
root.right.left.setValue(4)
root.right.left.print() // 4
root.print() // 3
// 指针接收者接收值;拷贝值的地址给指针接收者
root.setValue(100)
pRoot := &root
// 值接收者接收指针:把指针指向的值拷贝给值接收者
pRoot.print() // 100
// 指针接收者接收指针:拷贝指针给指针接收者
pRoot.setValue(300)
pRoot.print() // 300
root.traverse()
}
值接受者 vs 指针接收者
要改变内容必须使用指针接收者
结构过大也考虑使用指针接收者
建议(非强制):接收者的类型最好一致,即如有指针接收者,则最好都是指针接收者
值接收者是go语言特有的
值/指针接收者均可接收值/指针