Go中new和make的区别
变量声明
当我们声明变量时可以使用var关键字,当不指定变量的默认值时,这些变量的默认值就是他们的零值,比如int的默认值为0,string的默认值为"",引用类型的零值为nil。
但是当我们在声明引用类型的变量并直接使用时,会panic。
package mainimport "fmt"func main() {var i *int*i = 10fmt.Println(*i)
}//output: panic: runtime error: invalid memory address or nil pointer dereference
所以,对于引用型变量时,除了要声明它以外,还要为其分配空间。要分配内存,就需要使用make
或者new
。
new
上面的问题使用new
我们可以这样解决:
package mainimport "fmt"func main() {var i *inti = new(int)*i = 10fmt.Println(*i)
}
//output: 10
对于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
它只接受一个类型参数,内存分配完毕之后,会返回一个指向该内存的同类型的指针,同时将该内存的值改为该类型的零值。
再看一个例子:
package mainimport ("fmt""sync"
)type user struct {lock sync.Mutexname stringage int
}func main() {u := new(user)u.lock.Lock()u.name = "demo"u.lock.Unlock()fmt.Println(u)
}
在这个例子中可以看到使用new
的好处,在user中lock不需要自行的去初始化,new
之后,可以直接使用。
make
make
也是用于内存分配,但是和new
不同的是:它只用于chan、map以及切片的内存创建,而且它返回的类型就是这三个类型本身,而不是它们的指针类型,因为这三种类型就是引用类型,所以没有必要返回它们的指针。
func make(t Type, size ...IntegerType) Type
异同
二者都是在堆上进行内存分配,但make
只用于slice、map、channel的初始化;make
返回的还是这三个引用类型本身,而new
返回的是指向类型的指针;
为什么既有make
又有new
?
rujews:使用
make
的好处是可以指定len
和cap
,make(type,len,cap)
,合适的len
和cap
可以提升性能。YahuiAn:在使用make()函数创建切片时,如果我们能够预计出合理的容量大小(太大浪费内存空间,太小会不断的扩容),哪么我们在进行切片的append时,可能不会发生扩容,也就避免了切片元素的复制,减少了开销。