Go语言的面向对象

  • Go语言只支持封装,不支持继承和多态

  • 没有Class,只有Struct,也没有构造函数。

假设有一个结构体。

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

下面的类似构造函数,但是返回的是一个私有变量的地址给外面用,如果是其他语言,如何函数结束之后,私有变量也无法使用,导致程序报错。但是在go语言中下面这样写是没有问题的。同时,我们也不需要担心堆和栈的问题,这些垃圾回收机制都由go内部处理。

  1. 栈区(stack)--由编译器自动分配和释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

  2. 堆区(heap)--一般由程序员分配和释放,若程序员不释放,程序结束时可能由OS回收,注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

func CreateNode(value int) *Node {
	return &Node{Value: value}
}

为结构体定义方法

值接受者和指针接受者

  • 值接受者会拷贝一份给函数

  • 指针接受者会直接把指针地址里的值给函数

  • 值接受者是GO语言特有

  • 值/指针接受者均可接受值/指针

考虑

  • 结构过大也要考虑使用指针接受者

  • 所以只有使用指针才可以改变结构体内容!

nil指针也可以调用指针

func (node Node) Print() {
	fmt.Print(node.Value, " ")
}
//nil指针也可以调用指针
func (node *Node) SetValue(value int) {
	if node == nil {
		fmt.Println("Setting Value to nil " +
			"node. Ignored.")
		return
	}

封装

  • 名字一般使用CamelCase

  • 首字母大写:public

  • 首字母小写:private

  • 每个目录一个包

  • main包包含可执行的入口

  • 为结构定义的方法必须放在同一个包

  • 可以是不同文件

扩展

  • Go语言里没有继承

如果要扩充类型可以:

  • 定义别名

  • 使用组合

别名

type myTreeNode struct {
	node *tree.Node
}

func (myNode *myTreeNode) postOrder() {
	if myNode == nil || myNode.node == nil {
		return
	}

	left := myTreeNode{myNode.node.Left}
	right := myTreeNode{myNode.node.Right}

	left.postOrder()
	right.postOrder()
	myNode.node.Print()
}

组合

// A FIFO queue.
type Queue []int

// Pushes the element into the queue.
// 		e.g. q.Push(123)
func (q *Queue) Push(v int) {
	*q = append(*q, v)
}

// Pops element from head.
func (q *Queue) Pop() int {
	head := (*q)[0]
	*q = (*q)[1:]
	return head
}

// Returns if the queue is empty or not.
func (q *Queue) IsEmpty() bool {
	return len(*q) == 0
}

Last updated