Go语言的new和make

2018-03-09  本文已影响0人  高稚商de菌

在go语言中, 通过var声明变量时, 不指定默认值时, 就是使用他们的零值。 例如int类型的零值是0,string类型的零值是"",引用类型的零值是nil。
如果是引用类型, 那么直接通过var声明是不够的,还需用new或make来分配内存。

var b *int
//b := new(int)
fmt.Println(*b)
// 会报错
//panic: runtime error: invalid memory address or nil pointer dereference

golang的new和make主要区别如下:

1、make只能用来分配及初始化类型为slice,map,chan的数据;new可以分配任意类型的数据

2、new分配返回的是指针,即类型*T;make返回引用,即T;

3、new分配的空间被清零,make分配后,会进行初始化。(怎么理解)

4、对于struct的分配和初始化,除了可以使用new外,还可以这样做: T {},例如

package main
import (
    "fmt"
    "os"
)

func TestAlloc() {
    type T struct {
        n  string
        i  int
        f  float64
        fd *os.File
        b  []byte
        s  bool
    }

    var t1 *T
    t1 = new(T)
    fmt.Println(t1)

    t2 := T{}
    fmt.Println(t2)

    t3 := T{"hello", 1, 3.1415926, nil, make([]byte, 2), true}
    fmt.Println(t3)
}

func main() {
    TestAlloc()
}
&{ 0 0 <nil> [] false}
{ 0 0 <nil> [] false}
{hello 1 3.1415926 <nil> [0 0] true}

值得注意的是,如果使用T{}的方式初始化变量的话:

1、与C语言不同,T{}分配的局部变量是可以返回的,且返回后该空间不会释放,例如

import "fmt"
type T struct {
    i, j int
}
func a(i, j int) T {
    i := T { i, j}
    return i
}
func b() {
    t = a(1, 2)
    fmt.Println(t)
}

2、一个语法问题
使用T{}来初始化时,符号}不能单独占一行,否则会报错。

其他思考:

(a) 怎么理解 new分配的空间被清零,make分配后,会进行初始化?

答: make只用于slice, map, channel。 以slice为例。slice的零值是nil, 但是用make初始化后slice 是一个初始化的slice,即slice的长度、容量、底层指向的array都被make完成初始化。
例如make([]int,3)此时slice内容被类型int的零值填充,形式是[0 0 0],长度为3,容量不填默认等于长度这个参数。

(b) 怎么理解 make返回引用

答: 如果不特殊声明,go的函数默认都是按值穿参,即通过函数传递的参数是值的副本,在函数内部对值修改不影响值的本身,但是make(T,args)返回的值通过函数传递参数之后可以直接修改,即 map,slice,channel 通过函数穿参之后在函数内部修改将影响函数外部的值。

上一篇 下一篇

猜你喜欢

热点阅读