make和new对比|Go主题月

215 阅读3分钟

make

make只可以用来创建mapslicechan这三个类型,而且它是直接返回类型本身。可以看看它的源码介绍:

贴心的翻译了一下

// make内置函数分配并初始化一个切片,map或chan类型的对象。
// 与new相同点:第一个参数是类型,而不是具体值
// 与new不同点:make的返回类型与其参数相同的类型,而不是指向它的指针。
// 结果的规格取决于类型:
//
// 切片:大小指定长度。切片的容量等于其长度可以提供第二个整数参数指定其他容量;它必须不小于长度。
// 例如:make([] int,0,10)分配一个基础数组大小为10,并返回长度为0且容量为10的切片,即由该基础数组支持。
//
// map:为空map分配了足够的空间来容纳指定的元素数。在这种情况下,可以省略容量分配的起始大小较小。
//
// Channel:使用指定的值初始化通道的缓冲区容量。如果为零或忽略大小,则通道为无缓冲
func make(t Type, size ...IntegerType) Type

使用

// 切片
// 创建一个容量为0,长度为0的切片
slice1 := make([]int,0)
// 创建一个容量为10,长度为0的切片
slice2 := make([]int,0,10)

// map
// 创建一个没有指定容量的map
map1 := make(map[string]string)
// 创建一个指定容量为10的map
map2 := make(map[string]string,10)

// chan
// 创建一个缓冲容量为100的int通道
c := make(chan int,100)
// 创建一个无缓冲int通道
c2 := make(chan int)

new

new可以用来为类型在堆中申请内存(当然也包括mapslicechan)。返回的值是指向该类型新分配的零值的指针

源码介绍:

// new是内置函数分配内存。参数是类型,而不是值,返回的值是指向该类型新分配的零值的指针。
func new(Type) *Type

使用

// 创int  `*i`的默认值初始化为0
i := new(int)

// 创建一个长度为0  容量为0的切片
slice := new([]int)
  • 创建map就比较麻烦了,创建后还要进行初始化才可以继续使用

     //使用new创建一个map指针
    ma := new(map[string]int)                                                                                                                                          
    //第一种初始化方法
    *ma = map[string]int{}
    (*ma)["a"] = 44
    fmt.Println(*ma)
    
    //第二种初始化方法
    *ma = make(map[string]int, 0)
    (*ma)["b"] = 55
    fmt.Println(*ma)
    
    //第三种初始化方法
    mb := make(map[string]int, 0)
    mb["c"] = 66
    *ma = mb
    (*ma)["d"] = 77
    fmt.Println(*ma)
    

虽然官方提供了new这个函数,但是我们一般都比较少用它,因为确实不怎么方便。除非一些特殊的场景才会用到它。

比较

相同点:

  • 都是在堆上分配内存空间

不同点:

  • make: 只用于slice、map以及channel的初始化, 无可替代

  • new: 用于类型内存分配(初始化值为0), 不常用