话接上文
https://blog.csdn.net/wby90/article/details/106173343
https://blog.csdn.net/wby90/article/details/106043075
如果各位童鞋想要获得下面的源码,请搜索gzh:隔壁王小猿,关注后回复“Go语言基本语法”即可获得
Go语言仅支持封装,不支持多态和继承
Go语言没有class,只有struct
不论地址还是结构本身,一律使用 . 来访问
Root:=treeNode{value:3}
Root.left=&treeNode{}
Root.right=&treeNode{5,nil,nil}
Root.right.left=new(treeNode)
示例
var root treeNode
fmt.Println(root)
root = treeNode{
value: 3,
right: &treeNode{},
left: &treeNode{}}
fmt.Println(root)
root.left = &treeNode{5, nil, nil}
fmt.Println(root)
root.right.left = &treeNode{}
fmt.Println(root)
fmt.Println(root.left)
fmt.Println(root.right)
nodes := []treeNode{
{value: 3},
{right: &treeNode{}},
{value: 5, left: &treeNode{5, nil, nil}},
{3, nil, new(treeNode)}}
fmt.Println(nodes)
输出
{0 }
{3 0xc000004500 0xc0000044e0}
{3 0xc000004540 0xc0000044e0}
{3 0xc000004540 0xc0000044e0}
&{5 }
&{0 0xc000004580 }
[{3 } {0 0xc000004620} {5 0xc000004640 } {3 0xc000004600}]
工厂函数-模拟构造函数
返回的局部地址
func createNode(value int) *treeNode {
return &treeNode{value: value}
}
给结构体定义方法
显示定义和命名方法的接收者
使用指针作为方法接收者
只有使用指针才可以改变结构内容
nil指针也可以调用方法
示例
type treeNode struct {
value int
left, right *treeNode
}
func (node treeNode) printValue() {
fmt.Println(node.value)
}
//值传递 不会更改值
func (node treeNode) setValue(value int) {
node.value = value
}
//指针传递 会更改值
func (node *treeNode) setValuePointer(value int) {
node.value = value;
}
func createNode(value int) *treeNode {
return &treeNode{value: value}
}
var root treeNode
root.value = 3
root.left = &treeNode{}
root.right = &treeNode{5, nil, nil}
root.right.left = new(treeNode)
root.left.right = createNode(2)
fmt.Println("root value:")
root.printValue()
root.right.left.setValue(4)
fmt.Println("root.right.left value:")
root.right.left.printValue()
root.right.left.setValuePointer(4)
fmt.Println("root.right.left value:")
root.right.left.printValue()
输出
root value:
3
root.right.left value:
0
root.right.left value:
4
值接收者vs指针接收者
要改变内容必须使用指针接收者
结构过大也考虑使用指针接收者
一致性,如果有指针接收者,最好都是指针接收者
值接收者是go语言特有的
值、指针接收者均可接收值、指针
Go语言通过名字来区分public和private
名字一般使用CamelCase
首字母大写 public
首字母小写 private
每个目录一个包
mian包包含可执行入口
main函数所在目录只能有一个main包
为结构定义的方法必须在同一个包内,可以是不同文件
定义别名
使用别名myTreeNode封装TreeNode
type myTreeNode struct {
node *tree.TreeNode
}
//后续遍历
func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.node == nil {
return
}
//指针不能作为接收者, 需要需要定义变量来接送地址
//myTreeNode{myNode.node.Left}.postOrder();
left := myTreeNode{myNode.node.Left}
left.postOrder()
right := myTreeNode{myNode.node.Right}
right.postOrder()
myNode.node.PrintValue()
}
var root tree.TreeNode
root.Value = 3
root.Left = &tree.TreeNode{}
root.Right = &tree.TreeNode{5, nil, nil}
root.Right.Left = new(tree.TreeNode)
root.Left.Right = tree.CreateNode(2)
//root.Traverse()
pRoot := myTreeNode{&root}
pRoot.postOrder()
输出
2
0
0
5
3
使用组合
使用int组合实现queue
package queue
type Queue []int
func (q *Queue) Push(v int) {
*q = append(*q, v)
}
func (q *Queue) Pop() int {
if q == nil {
panic("error.")
}
head := (*q)[0]
*q = (*q)[1:]
return head
}
func IsEmpty(q *Queue) bool {
return len(*q) == 0
}
GOPATH环境变量
默认~/go(linux,unix), %USERPROFILE%\go(windows)
官方推荐:所有项目和第三方库都放在一个GOPATH下
也可以将每个项目放在不同的GOPATH
Go get 命令获取包,也可以用gopm获取
GOPATH下目录结构
Src
Git rep1
Git rep2
Pkg
Git rep1
Git rep2
Bin
可执行文件
先问一个比较考三观的问题:图片中的大黄鸭,它是不是一只鸭子呢?
Duck Typing 的原话是,走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么它就是一只鸭子。
这个原话是可以灵活理解的,就看我们怎么定义鸭子的行为,我们可以说,能浮在水上游的,黄色的,可爱的就是鸭子,那么,图片中的大黄鸭,它就是一只鸭子!
这就是所谓的 Duck Typing,它只关心事物的外部行为而非内部结构。它并不关心你这只鸭子是长肉的还是充气的。
Def download(retriever):
Return retriever.get(“www.baidu.com”)
运行时才知道传入的retriever有没有get
需要注释来说明接口
Template
Def download(const R& retriever){
Return retriever.get(“www.baidu.com”);
}
编译时才知道传入的retriever有没有get
需要注释来说明接口
String download(R r){
Return r.get(“www.baidu.com”);
}
传入的参数必须实现Retriever接口,编写代码过程中就知道必须包含get方法
不是duck typing
同时可以实现多个接口
具有python和c++ 的duck typing的灵活性
又具有Java的类型检查
类似duck typing
Go语言接口是由使用者定义的
type Retriever interface {
Get(url string) string
}
接口的实现是隐式的
type Retriever struct {
Context string
}
func (r Retriever) Get(url string) string {
return r.Context
}
接口变量自带指针
接口变量同样采用值传递,几乎不需要使用接口的指针
指针接收者实现只能以指针方式使用,值接收者都可
表示任何类型:interface{}
Type Assertion
Type Switch
type getItf interface {
Get(url string) string
}
type postItf interface {
Post(url string, from map[string]string) string
}
type getAndPostI interface {
getItf
postItf
}
func adder() func(int) int {
sum := 0
return func(v int) int {
sum += v
return sum
}
}
func main() {
a := adder();
for i := 0; i < 10; i++ {
fmt.Println(a(i))
}
}
adder函数返回的是一个闭包,不仅仅是一个函数,还包含sum的引用等