Skip to content

面向“对象”

  • 结构的创建:不论地址还是结构本身,一律使用 . 来访问成员。
    package main
    
    import "fmt"
    
    type treeNode struct {
        value       int
        left, right *treeNode
    }
    
    // 方法
    func (node treeNode) print() {
        fmt.Print(node.value, " ")
    }
    
    // 传值
    func (node *treeNode) setValue(value int) {
        if node == nil {
            fmt.Println("setting value to nil node.")
            return
        }
        node.value = value
    }
    
    // 树的遍历
    //func (node *treeNode) traverse() {
    //    if node == nil {
    //        return
    //    }
    //    node.left.traverse()
    //    node.print()
    //    node.right.traverse()
    //}
    
    // 工厂函数
    func createNode(value int) *treeNode {
        return &treeNode{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.left.right = createNode(2)
    
        root.right.left.setValue(4)
        //root.traverse()
        /*
         0 2 3 4 5
        */
        root.right.left.print()
        /*
        4
        */
        fmt.Println()
    
        root.print()
        root.setValue(100)
    
        //pRoot := &root
        //pRoot.print()
        //pRoot.setValue(200)
        //pRoot.print()
        /*
        4
        3 100 200
        */
    
        var pRoot *treeNode
        pRoot.setValue(200)
        pRoot = &root
        pRoot.setValue(300)
        pRoot.print()
        /*
        4
        3 setting value to nil node.
        */
    
        //nodes := []treeNode{
        //  {value: 3},
        //  {},
        //  {6, nil, &root},
        //}
        //fmt.Println("nodes", nodes)
        /*
        nodes [{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc000010030}]
        */
    }
    

结构体和方法

  • 结构体

    • 使用自定义工厂函数
    • 注意返回了局部变量的地址
      func createTreeNode(value int) *TreeNode {
          return &TreeNode{Value: value}
      }
      
      root.Left.Right = createTreeNode(2)
      
  • 方法

    • 显示定义和命名方法接收者
      func (node TreeNode) print() {
          fmt.Print(node.Value)
      }
      
    • 使用指针作为方法接收者
      • 只有使用指针才可以改变结构内容
        func (node *TreeNode) setValue(value int) {
            node.Value = value
        }
        
      • nil指针也可以调用方法
        func (node *treeNode) setValue(value int) {
            if node == nil {
                fmt.Println("setting value to nil node.")
                return
            }
            node.value = value
        }
        
  • 值接受者 vs 指针接收者

    • 区别
      • 要改变内容必须使用指针接收者,值接收者只是个拷贝
      • 结构过大也考虑使用指针接受者,数据共享
      • 一致性:建议如果有指针接收者,最好都是指针接收者
    • 值接收者 是go语言特有的
    • 值/指针接收者均可接收值/指针

包和封装

  • 函数作用域是否可见是通过函数命名来做的
  • 首字母大写:public
  • 首字母小写:private

  • 每个目录一个包
  • main包包含可执行入口
  • 为结构定义的方法必须放在同一个包内
  • 可以是不同的文件

package tree

import "fmt"

type Node struct {
    Value       int
    Left, Right *Node
}

// 方法
func (node Node) Print() {
    fmt.Print(node.value, " ")
}

// 传值
func (node *Node) SetValue(value int) {
    if node == nil {
        fmt.Println("setting value to nil node.")
        return
    }
    node.Value = value
}

// 树的遍历
func (node *Node) Traverse() {
    if node == nil {
        return
    }
    node.Left.Traverse()
    node.Print()
    node.Right.Traverse()
}

// 工厂函数
func Node(value int) *Node {
    return &Node{Value: value}
}
package main

import "advanced/tree"

func main() {

    var root tree.Node
    root = Node{value: 3}
    root.Left = &Node{}
    root.Right = &Node{5, nil, nil}
    root.Right.left = new(Node)
    root.Left.right = Node(2)

    root.Right.left.setValue(4)

    root.traverse()
    //  0 2 3 4 5
}

扩展已有类型

  • 如何扩充系统类型或者别人的类型
    1. 定义别名
    2. 使用组合

GOPATH以及目录结构

  • 官方推荐扩展和src在GOPATH目录下