在面向对象中,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语言特有的
    值/指针接收者均可接收值/指针