【笔记】go语言--结构体,方法,包与封装

【笔记】go语言--结构体,方法,包与封装

结构体和方法

面向对象

  • go语言仅支持封装,不支持继承和多态
  • go语言没有class,只有struct
//结构的定义
type TreeNode struct {
	Left,Right *TreeNode
	Value int
}

//结构体的创建
root := TreeNode{Value: 3}
root.Left = &TreeNode{}
root.Right = &TreeNode{nil, nil,5}
root.Right.Left = new(TreeNode)

需要注意,不论地址还是结构本身,一律使用.来访问成员

//此为自定义工厂函数,接结构体的创建,go语言可实现返回局部变量
func createTreeNode(value int) *TreeNode {
	return &TreeNode{Value: value}
}
root.Left.Right = createTreeNode(2)

使用自定义工厂函数,同时注意返回了局部变量的地址!

既然知道能够返回局部变量的地址,那么结构创建在堆上还是栈上了呢?

看情况,有go语言的编译器和运行环境来决定,如果这个局部变量让编译器认为没有取地址并且返回出去,认为这个局部变量不需要给外面使用,那么就会在栈上分配

但是,如果编译器认为这个局部变量通过取地址并且返回出去给别人用,那么这个局部变量就会在会在堆上分配,堆上分配完后,这个局部变量就会参与垃圾回收,等外部调用这个指针使用完后,这个指针就会被回收。

为结构体定义方法

//调用结构体,值接受者与指针接受者

//为结构体定义方法,显示定义和命名方法接受者
func (node treeNode) print() {
	fmt.Print(node.value)
}

//使用指针作为方法接受者,只有使用指针才可以改变结构内容,同时nil指针也可以调用方法
func (node *treeNode) setValue(value int) {
	node.value = value
}

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.right.left.print()
}

//中序遍历
func ( node *treeNode) traverse() {
	if node == nil {
		return
	}
	node.left.traverse( )
	node.print( )
	node.right.traverse( )
}

值接收者vs指针接收者

  • 要改变内容必须使用指针接收者
  • 结构过大也考虑使用指针接收者
  • —致性:如有指针接收者,最好都是指针接收者
  • 值接收者是go语言特有的
  • 值/指针接收者均可接收值/指针

包和封装

封装

  • 名字一般使用CamelCase
  • 首字母大写:public,代表全局可见,即公有方法
  • 首字母小写:private,代表包内可见,即私有方法

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

问题:如果包是别人写的,我们如何调用?

如何扩充系统类型或者别人的类型

  • 定义别名:最简单,别名是使用type 声明一个别名,然后给自己别名定义新的方法
  • 使用组合:最常用,组合指的是用自己的type类型包装一个原来的类型
  • 使用内嵌:需要省下许多代码,内嵌方式,在结构体中省略字段名,只包含一个指针类型名,则该类型的各个方法会被结构体继承,同时还可以重载原来类型的方法,也就是重新定义同名方法。类似于继承的关系
posted @ 2022-02-07 20:28  DbWong_0918  阅读(191)  评论(0编辑  收藏  举报