Go 语言编程 — make 和 new

目录

文章目录

  • 目录
  • make 和 new
  • 为什么建议使用 make 来定义 Slice、Map 和 Channel 变量?

make 和 new

make 和 new 都是 Golang 的内置函数,作为用于内存分配的原语(Allocation Primitives),其功能相似,却有着本质的区别。

  • new 用来分配内存,它的第一个参数是一个类型,不是一个值,返回值是一个指向为特定类型新分配的零值填充的内存空间的指针。它并不初始化内存,只是将其置零。相当于 C 语言中的 memset 0。
// 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

make 只能用于为 Slice、Map 或 Channel 类型分配内存并进行初始化,所以其除了第一个参数传入一个类型之外,还可以传入用于完成初始化的可变长的 size 实参。跟 new 不同的是,make 返回类型的引用而不是指针,而返回值也依赖于具体传入的类型。

//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.

func make(t Type, size ...IntegerType) Type

为什么建议使用 make 来定义 Slice、Map 和 Channel 变量?

先来看一下以上三个数据结构的源码:

  • Slice
type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}
  • Map
type hmap struct {
    count      int 
    flags      uint8
    B          uint8  
    noverflow  uint16 
    hash0      uint32 
    buckets    unsafe.Pointer 
    oldbuckets unsafe.Pointer 
    nevacuate  uintptr      
    extra *mapextra 
}
  • Channel
type hchan struct {
    qcount   uint           
    dataqsiz uint          
    buf      unsafe.Pointer
    elemsize uint16         
    closed   uint32        
    elemtype *_type 
    sendx    uint  
    recvx    uint  
    recvq    waitq 
    sendq    waitq  
    lock mutex
}

可见,上述三个类型的背后都引用了使用前必须完成初始化的成员数据结构。如果我们使用常规的方式创建变量(e.g. var map1 [string]int)的话,很可能会出现仅仅声明了,但却没有完成初始化的定义,从而在后续的代码中留下错误的隐患。而 make() 函数,时刻提供我们完成一个切实的变量定义(声明并初始化)。

你可能感兴趣的:(Golang)