1.说明

1)go中的struct与C中的struct非常相似,并且go没有class

2)使用type <Name> struct {}定义结构,名称遵循可见性规则

3)支持指向自身的指针类型成员

4)支持匿名结构,可用作成员或定义成员变量

5)匿名结构也可以用于map的值

6)可以使用字母值对结构体进行初始化

7)允许直接通过指针类读写结构成员

8)相同类型的成员可以进行直接拷贝赋值

9)支持==与!=比较运算符,但不支持>或<

10)支持匿名字段,本质上是定义了以某个类型名为名称的字段

11)嵌入结构作为匿名字段看起来像继承,但不是继承

12)可以使用匿名字段指针

13)go语言仅支持封装,不支持继承和多态

14)go没有class,只有struct

 

实例,创建一棵树的数据结构

package main

import "fmt"

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

func main() {
    var root treeNode
    //初始为空
    fmt.Println(root)
    //几种不同的创建树的方法
    root = treeNode{value: 3}
    root.left = &treeNode{}
    root.right = &treeNode{5, nil, nil}
    root.right.left = new(treeNode)

    nodes := []treeNode{
        {value: 3},
        {},
        {6, nil, &root},
    }
    //打印查看创建的结构
    fmt.Println(nodes)
}

输出:
API server listening at: 127.0.0.1:36962
{0 <nil> <nil>}
[{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc0420503e0}]
2.工厂函数

//go语言结构中没有构造函数,但是可以创建一个工厂函数来负责创建结构

func createNode(value int) *treeNode {
    //go语言中返回一个局部变量的地址是可以给外部使用的
    return &treeNode{value: value}
}

root.left = createNode(100)

实例:

package main

import "fmt"

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

func (node treeNode) print() {
    fmt.Println(node.value)
}

//go语言结构中没有构造函数,但是可以创建一个工厂函数来负责创建结构
func createNode(value int) *treeNode {
    //go语言中返回一个局部变量的地址是可以给外部使用的
    return &treeNode{value: value}
}

func (node treeNode) setVale(value int) {
    node.value = value
    node.print()
}

func (node *treeNode) setValePtr(value int) {
    node.value = value
    node.print()
}

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.print() //这里有个接收者,root相当于参数,值传递
    root.right.print()
    root.right.left.print()
    root.left.right.print()
    fmt.Println()
    //检验接收者值传递,传入一个值在局部打印,之后在主函数打印观察是否被修改
    fmt.Println("#####################")
    root.right.left.print()
    root.right.left.setVale(100)
    root.right.left.print()
    //地址传入测试,这样发现内容会被修改
    fmt.Println("#####################")
    root.right.left.print()
    root.right.left.setValePtr(100)
    root.right.left.print()
}

输出:
5
0
2
#####################
0
100
0
#####################
0
100
100


上述发现,只有指针传入的时候内容才会被修改,其他值专递情况不会修改内容,这里可以总结为:

1)只有使用指针才可以改变结构内容

3)nil指针也可以调用方法

 

实例:遍历一棵树

package main

import "fmt"

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

func (node treeNode) print() {
    fmt.Printf("%d ", node.value)
}

//go语言结构中没有构造函数,但是可以创建一个工厂函数来负责创建结构
func createNode(value int) *treeNode {
    //go语言中返回一个局部变量的地址是可以给外部使用的
    return &treeNode{value: value}
}

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

    node.left.traverse()
    node.print()
    node.right.traverse()
}

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.traverse()
}

输出:
API server listening at: 127.0.0.1:33038
0 2 3 0 5

接收者总结,指针接收者和值接收者应该如何使用

1)要改变内容必须使用指针接收者

2)结构过大也考虑使用指针接收者

3)一致性,如果有指针接收者最好使用指针接收者