面向对象

结构体和方法

go语言仅支持封装,不支持多态和继承,使用接口来实现。
因此只有struct,没有class。
一律使用点来访问成员。

type treeNode struct {
	value int
	left, right *treeNode
}

func main() {
	var root treeNode
	//go语言提供了非常多的构造方法,因此没有构造函数的说法
	root = treeNode{value:3}
	root.left = &treeNode{}
	root.right = &treeNode{5, nil,nil}
	root.right.left = new(treeNode) //创建空的treeNode,返回地址

	nodes := []treeNode{
		{value:4},
		{},
		{6,nil,&root},
	}
	fmt.Println(nodes)
}

结构的创建,注意返回的是局部变量的地址。
在C++中,局部变量是分配在栈上的,因此在返回之后,这个栈上的数据会被销毁,若要使得返回之后还存在,必须在堆上进行分配,但是在堆上分配必须进行手动释放。
在go语言中,结构创建是在堆上还在栈上?不需要知道,这个是由编译器和运行时的环境来决定的,如果下面的treeNode没有取地址并且返回的话,编译器就有可能将其分配在栈上,若下面的treeNode取地址并且返回的话,编译器就有可能将其分配在堆上,就会参与垃圾回收。

//可以提供工厂函数
func createNode(value int) *treeNode{
	return &treeNode{value:value} //这里返回的是局部变量的地址,如果在C++中程序会挂掉,go语言中不会挂
}

go语言给结构体定义方法,是放在结构体外面的。在函数名字的前面有一个小括号,相当于其他语言中的this。

//方法的定义 vs 函数的定义
func (node treeNode) print() {
	fmt.Println(node.value)
}
func print1(node treeNode) {
	fmt.Println(node.value)
}
//这两个是一样的,只是语法上不同
root.print()
print1(root) 
//也是进行值传递,这对原来的value是改变不了的。
func (node treeNode) setValue() {
	node.value = 100
}
func (node *treeNode) setValue(value int) {
	if node == nil{
		fmt.Println("nil")
		return
	}
	node.value = value //不需要写成(*node)->value = value
}

在go语言中,对于值接收者和指针接收者,要值就拷贝一份,要指针就取地址。

  • 要改变内容的话,必须使用指针接收者;
  • 结构过大的话,也需要考虑使用指针接收者;
  • 一致性:如果有指针接收者,最后使用指针接收者;
  • 值接收者是go语言特有的,C++的this是指针接收者
  • 值/指针接收者均可以接收值/指针接收者。

nil指针也可以调用方法!

root = treeNode{value:3}
root.print() 
root.setValue(100) // 而不需要写成(&root)->setValue()

var pRoot *treeNode
pRoot.setValue(200)

包和封装

名字一般使用CamelCase
首字母大写:public
首字母小写:private
每个目录只能是一个包名,main包包含可执行入口
为结构定义的方法必须放在同一个包内,可以是不同的文件

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

  • 定义别名
  • 使用组合
//使用组合
type myTreeNode struct {
	node *tree.TreeNode
}
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()
}
//重命名
type Queue []int

func (q *Queue) Push(v int)  {
	*q = append(*q,v) //使用系统的类型的时候,必须加上*号来解引用
}

func (q *Queue) Pop() int {
	head := (*q)[0]
	*q = (*q)[1:]
	return head
}

func (q *Queue) IsEmpty() bool {
	return len(*q) == 0
}

GOPATH环境变量

默认在~/go(unix, linux),%USERPROFILE%\go(windows)
官方推荐:所有项目和第三方库都放在同一个GOPATH下。也可以将每个项目放在不同的GOPATH下。
由于网络的原因,使用go get通常无法获取国外服务器上的文件。
可以先使用go get下载gopm, go get -v github.com/gpmgo/gopm。
使用gopm下载好了包之后,使用go install来安装,产生pkg文件和可执行文件,之后的可执行文件放在了$GOPATH/bin中。go build进行编译。go run直接编译运行。
使用goimports工具可以在保存文件的时候,自动整理go文件中的import内容,将没有用到的库删除,或者自动引入别的库。

通过gopm get xxx,可以将指定的包下载到gopm的本地仓库~/.gopm/repos(建议使用) 通过’gopm get -g xxx’,可以将指定的包下载到GOPATH下。(建议使用) 通过’gopm get -l xxx’,可以将指定的包下载到当前所在目录(不常用)。
gopm get -g golang.org/x/net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值