new 和 make 的区别
# make 和 new 的区别
# new
# 函数签名
new的函数签名:
func new(Type) *Type
1
参数说明:
Type:需要new的类型。- 返回值是指向
Type的指针,新分配的值为Type的零值。
# 作用
new主要用于分配内存, 但与其它语言中的同名函数不同,它不会初始化内存,只会将内存置零。 也就是说,new(T) 会为类型为T的新项分配已置零的内存空间, 并返回它的地址(即*T)。用 Go 的术语来说,它返回一个指针, 该指针指向新分配的,类型为T的零值。
例如下面这个例子,i是一个int类型的指针,但是没有分配内存空间,因此是不能赋值的。执行这个测试会报错:invalid memory address or nil pointer dereference。
/*
TestVariable 会报错
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4f503b]
*/
func TestVariable(t *testing.T) {
var i *int
*i = 10
t.Log(*i)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
现在使用new来分配内存:
func TestNew_int(t *testing.T) {
var i *int
i = new(int)
fmt.Println(*i) // 0 提示:int 的零值为 0
*i = 1
fmt.Println(*i) // 1
}
1
2
3
4
5
6
7
2
3
4
5
6
7
现在重新执行这个测试,可以通过了。
# make
# 函数签名
make的函数签名:
func make(t Type, size ...IntegerType) Type
1
make和new一样,第一个参数是一个类型,而不是一个值。与new不同的是,make的返回类型与其参数的类型相同,而不是指向它的指针。
# 作用
make不同于new,它仅限于slice、map和chan的初始化(分配内存空间,而非置零),同时它接收三个参数。第一个参数是类型,第二个是该类型的长度,第三个是该类型的容量。出现这种用差异的原因在于,这三种类型本质上为引用数据类型,它们在使用前必须初始化。
注意:如果第一个参数是map类型,那么make只接收两个参数,第二个是容量。
下面这个例子是创建一个长度为0,容量为10的int类型的切片(slice):
func TestMake_slice(t *testing.T) {
l := make([]int, 0, 10)
fmt.Println(l == nil) // false
fmt.Printf("len: %d cap: %d\n", len(l), cap(l)) // len: 0 cap: 10
l = append(l, 1)
fmt.Println(l) // [1]
}
1
2
3
4
5
6
7
2
3
4
5
6
7
使用new来创建的切片并不能指定长度和容量,返回的是指向切片的指针:
func TestNew_slice(t *testing.T) {
l := new([]int)
fmt.Println(*l == nil) // true
fmt.Printf("len: %d cap: %d\n", len(*l), cap(*l)) // len: 0 cap: 0
*l = append(*l, 1)
fmt.Println(*l) // [1]
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# new与make的异同
# 相同点
new和make都是用于给指定的类型分配内存空间。
# 不同点
make仅限于slice、map和chan的初始化。make接收的参数比new多,它的返回值是slice、map或chan这个三个类型本身,而不是它们的指针类型,因为这三种就是引用类型。new用于类型内存分配(初始化值为类型的零值),返回值是指向Type的指针。
提示:不要使用new,永远用 make 来构造 map。如果你错误的使用new分配了一个引用对象,你会获得一个空引用的指针,相当于声明了一个未初始化的变量并且取了它的地址:
func TestNew_map(t *testing.T) {
m := new(map[string]int)
fmt.Println(*m == nil) // true
(*m)["key"] = 1 // panic: assignment to entry in nil map
}
1
2
3
4
5
2
3
4
5
上次更新: 2024/05/29, 06:25:22