Go语言中new()和make()的区别

1. Go语言中的值类型和引用类型

  • 值类型:int,float,bool,string,struct数组 (数组要特别注意,别搞混了)

变量直接存储值,分配栈区的内存空间,这些变量所占据的空间在函数被调用完后会自动释放。

  • 引用类型:slice,map,chan和值类型对应的指针

变量存储的是一个地址(或者理解为指针),指针指向内存中真正存储数据的首地址。内存通常在堆上分配,通过GC回收。

 

2. new() vs make()

对值类型和引用类型了解之后,再来理解new()和make()就不难了,其实只要有C/C++背景的理解起来都不难。比如我们声明一个int类型的数据,一般是这样的:

var i int

var s string 

当我们不指定变量的默认值时,这些变量的默认值就是对应的零值。(int类型的零值是0,string类型的零值是"",引用类型的零值是nil)。我们可以直接对值类型的变量进行赋值,修改变量对应的值等等。但是,如果声明的变量是引用类型呢?这就需要用到new()或make()函数了。先来看这样一个例子:

var i int // 值类型
i = 10
fmt.Println(i) // 10

var p *int // 引用类型
*p = 10
fmt.Println(*p) //panic: runtime error: invalid memory address or nil pointer dereference

从例子可以看到,当对指针p进行赋值的时候,出现了panic,提示p 是无效的内存地址或是空指针引用。也就是说,对于引用类型的变量,我们不仅要声明变量(这仅仅是给变量取个名字),更重要的是,我们得手动为它分配空间!好在Go中还有GC,如果是C/C++,对于指针类型,除了手动申请空间,更要手动释放空间。

new()方法就是为 int/bool/struct等 值类型分配内存空间,返回相应类型的指针;而make()就是专为slice,map,channel分配空间。

 

new()

该方法的参数要求传入一个类型,而不是一个值,它会申请一个该类型大小的内存空间,并会初始化为对应的零值,返回指向该内存空间的一个指针。如下:

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

因此,我们可以稍稍修改上面错误的程序.

var p *int // 引用类型,或者写成 p := new(int)
p = new(int)
*p = 10
fmt.Println(*p) // 10 

 

make()

make也是用于内存分配,但是和new不同,它只用于slice、map和channel的内存创建,它返回的类型就是类型本身,而不是它们的指针类型。

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//    Slice: The size specifies the length. The capacity of the slice is
//    equal to its length. A second integer argument may be provided to
//    specify a different capacity; it must be no smaller than the
//    length. For example, make([]int, 0, 10) allocates an underlying array
//    of size 10 and returns a slice of length 0 and capacity 10 that is
//    backed by this underlying array.
//    Map: An empty map is allocated with enough space to hold the
//    specified number of elements. The size may be omitted, in which case
//    a small starting size is allocated.
//    Channel: The channel's buffer is initialized with the specified
//    buffer capacity. If zero, or the size is omitted, the channel is
//    unbuffered.
func make(t Type, size ...IntegerType) Type

 

posted @ 2020-03-21 17:25  kkbill  阅读(1817)  评论(1编辑  收藏  举报