美文网首页
Go语言学习之——struct

Go语言学习之——struct

作者: 星空_ad64 | 来源:发表于2018-04-10 20:42 被阅读0次

    go语言仅支持封装,不支持继承和多态
    go语言没有class,只有struct


    1、初始化

    package main
    ​
    import "fmt"
    ​
    type treeNode struct {
        value int
        left, right *treeNode
    }
    ​
    func main() {
        var root treeNode
        fmt.Println(root) // output:{0 <nil> <nil>}
        
        root = treeNode{value:3}
        root.left = &treeNode{}
        root.right = &treeNode{5, nil, nil }
        root.right.left = new(treeNode)
        fmt.Println(root) // output:{3 0xc0420024a0 0xc0420024c0}
    ​
        nodes := []treeNode{
            {value:3},
            {},
            {6, nil, &root },
        } // output:[{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc042002440}]
        fmt.Println(nodes)
    }
    

    2、可以使用自定义工厂函数

    package main
    ​
    import "fmt"
    ​
    type treeNode struct {
        value int
        left, right *treeNode
    }
    ​
    func createNode( value int ) *treeNode{
        return &treeNode{value:value}
    } // 返回的是局部变量的地址,go中是允许的
    ​
    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)
        root.left.right = createNode(8)
        fmt.Println(root)
        fmt.Println(*root.left.right) // output:{8 <nil> <nil>} root.right.right是指针,想看内容要加*
    }
    

    C++中,函数中局部变量分配在栈上,一旦函数退出,变量就被销毁,如果需要传出去,就要分配在堆上,分配在堆上的需要手动释放
    Java中几乎所有东西都分配在堆上,都需要new
    go语言不需要知道。。。。它会自己决定在哪里分配,如果需要返回就分配在堆上,后面会参与垃圾回收,如果不需要返回,就分配在栈上。


    3、结构的方法

    package main
    ​
    import "fmt"
    ​
    type treeNode struct {
        value int
        left, right *treeNode
    }
    ​
    // struct的方法,需要在函数名前加(node treeNode),叫做接受者,相当于其他语言的this,功能和普通函数的参数差不多
    func (node treeNode) print() {
        fmt.Println(node.value)
    }
    ​
    // 普通函数
    func print2(node treeNode) {
        fmt.Println(node.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(8)
    ​
        root.print() // output:3 和普通函数只是调用方法不太相同,其他差不多。
        print2(root) // output:3
    }
    

    接收者相当于普通函数的传参,也是值传递

    package main
    ​
    import "fmt"
    ​
    type treeNode struct {
        value int
        left, right *treeNode
    }
    ​
    func (node treeNode) print() {
        fmt.Println(node.value)
    }
    ​
    // 值传递,所以并不能改变value值
    func (node treeNode) setValue( value int ) {
        node.value = value
    }
    ​
    // 传地址,用指针作为接受者,能够改变value值
    func (node *treeNode) realSetValue( value int ) {
        node.value = value
    }
    ​
    // nil指针也可以调用方法,传进去的可以是nil,只要传进去之后再判断是不是nil就可以
    func (node *treeNode) traverse() {
        if node == nil {
            return
        }
    ​
        // 如果是C++等语言,需要先判断node.left != None,才能调用,但因为go中nil也可调用方法,so不需要判断
        node.left.traverse() 
        node.print()
        node.right.traverse()
    }
    ​
    func createNode( value int ) *treeNode{
        return &treeNode{value:value}
    }
    ​
    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)
        root.left.right = createNode(8)
    ​
        // 值接受者和指针接受者并不影响调用
        root.left.print() // output:0
        root.left.setValue(7) // 调用时,拷贝一份传给函数
        root.left.print() // output:0 其value值并没有改变
        root.left.realSetValue(7) // 调用时,会把地址给函数
        root.left.print() // output:7 能够改变
        
        // 取地址后,也可以调用两个函数,编译器会根据接受者类型自动判断如果给函数传参
        pRoot := &root
        pRoot.print() // output: 3
        pRoot.realSetValue(20)
        pRoot.print() // output: 20
        
        root.traverse() // output: 7 8 20 0 5
    }
    

    需要改变内容必须使用指针接受者,结构过大考虑使用指针接受者,建议如果有指针接受者,最好都使用指针接受者

    相关文章

      网友评论

          本文标题:Go语言学习之——struct

          本文链接:https://www.haomeiwen.com/subject/ontohftx.html