美文网首页
go的make slice坑, defer闭包坑, 变量类型坑

go的make slice坑, defer闭包坑, 变量类型坑

作者: 以梦为马驾驾驾 | 来源:发表于2022-01-29 14:58 被阅读0次

    make slicek

    我记得这几乎是每个使用go的同学都会遇到的:

    students := make([]Student, 0, 10)  
    students2 := make([]Student, x, 10)
    

    make在slice的时候,会根据第二个参数的值, 使用这个类型默认的零值来构建对应数量的对象.0的时候,整个slice是0个元素, x的时候,是已经存在了x个元素(值为此类型的零值).
    另外关于slice当做方法参数传递的时候,会复制slice自身,而不会复制底层依赖的数据就没什么可说的.

    defer闭包

    首先defer是倒序执行的

        fun := func(t int) {
            println(strconv.Itoa(t))
        }
    
        y := 10
        //1.
        defer fun(y)
    
        //2
        defer func() {
            println("\n2.")
            fun(y)
        }()
    
        y = 20
    
    ==>
    2.
    20
    10
    
    1. 在压入defer栈的时候,已经复制了y的值10, 2.在压栈的时候是压入了函数, 函数引向外部的y变量.
      同理
    pointX := &SomeStrunct(123)
    
    defer  pointX.SomeMethod()
    
    defer func() {
    println("我是func包住的")
      pointX.SomeMethod()
    }
    
    pointX = &SomeStruct(456)
    
    ==>
    两个defer
    按照顺序执行后输出
    
    我是func包住的
    456
    
    123  // 这个是第一个defer输出的, pointX在压入栈的时候, 已经计算好pointX的值了.
    
    
    

    defer函数可能是空指针

    因为defer常备用来清理资源,但是如果某个资源创建失败, 它的defer如果还会执行的话, 写的不好,会报错:

    xx , err:= createSomeResources()
    不判断err
    defer Close(xx) // err 不为nil的时候,xx是nil, 可能defer出错
    

    变量类型

    值类型,引用类型
    值类型直接指向一块存有值的内存空间, 指针类型的内存空间里存着的是一块内存地址的位置, 指针类型自己存在一块内存空间, 所以自己也可以被取地址, 引用类型相当于指针类型的别名, 也可以被取地址, 但是这是它本身的地址, 而不是它所代表的数据的地址.

    引用类型变量: slice, map, channel
    除外都是值类型

    因为值类型存在栈上,而引用类型的一般放堆上,所以, 需要主动分配内存.
    对于值类型, 申明就可以 申明 + 分配内存
    对于引用类型, 申明就只是申明, 还需要分配内存空间

    分配空间又有两种方式:

    1. new
    2. make

    new 它只接受一个参数,这个参数是一个类型,分配好内存后,返回一个指向该类型内存地址的指针。同时请注意它同时把分配的内存置为零,也就是类型的零值。new(int)
    //slice
    ss := new([]int)
    println(ss) // [0/0]0x0 == nil
    sss := append(
    ss, 2)
    print(sss[0])
    var yy []int
    println(yy) // [0/0]0x0 == nil
    yyy := append(yy, 3)
    print(yyy[0])
    // slice 特别的是不需要初始化也能append
    //map
    m := new(map[int]int)
    println(*m) // 0x0 nil
    ma := *m
    ma[1] = 2 // panic
    // map 就需要初始化

    make也是用于内存分配的,但是和new不同,它只用于chan、map以及切片的内存创建,而且它返回的类型就是这三个类型本身, 而且是初始化过的,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。
    注意,因为这三种类型是引用类型,所以必须得初始化,但不是置为零值,这个和new是不一样的. func make(t Type, size ...IntegerType) Type
    从函数声明中可以看到,返回的还是该类型。

    相关文章

      网友评论

          本文标题:go的make slice坑, defer闭包坑, 变量类型坑

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