Go

Make、New之内存分配

new 是一个分配内存的内建函数,但不同于其他语言中同名的new所作的工作,它只是将内存清零,而不是初始化内存。new(T)为一个类型为T的新项目分配了值为零的存储空间并返回其地址,也就是一个类型为*T的值。用Go的术语来说,就是它返回了一个指向新分配的类型为T的零值的指针

 func main() {     
      var a *int     
      *a = 100     
      fmt.Println(*a)     

      var b map[string]int     
      b["测试"] = 100     
      fmt.Println(b) 
} 

执行上面的代码会引发panic,为什么呢? 在Go语言中对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则我们的值就没办法存储。而对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已经默认分配好了内存空间。要分配内存,就引出来今天的new和make。 Go语言中new和make是内建的两个函数,主要用来分配内存

示例代码中var a *int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。

make(T, args)函数的目的与new(T)不同。它仅用于创建切片、map和chan(消息管道),并返回类型T(不是*T)的一个被初始化了的(不是)实例。这种差别的出现是由于这三种类型实质上是对在使用前必须进行初始化的数据结构的引用。例如,切片是一个具有三项内容的描述符,包括指向数据(在一个数组内部)的指针、长度以及容量,在这三项内容被初始化之前,切片值为nil。对于切片、映射和信道,make初始化了其内部的数据结构并准备了将要使用的值。如:

下面的代码分配了一个整型数组,长度为10,容量为100,并返回前10个数组的切片 :

make([]int, 10, 100)

以下示例说明了newmake的不同。

var p *[]int = new([]int)   // 为切片结构分配内存;*p == nil;很少使用
var v  []int = make([]int, 10) // 切片v现在是对一个新的有10个整数的数组的引用
 
// 不必要地使问题复杂化:
var p *[]int = new([]int)
fmt.Println(p) //输出:&[]
*p = make([]int, 10, 10)
fmt.Println(p) //输出:&[0 0 0 0 0 0 0 0 0 0]
fmt.Println((*p)[2]) //输出: 0
 
// 习惯用法:
v := make([]int, 10)
fmt.Println(v) //输出:[0 0 0 0 0 0 0 0 0 0]

发表评论