发布时间:2024-11-24 18:08:47
在golang中,我们经常使用new和make来创建变量。虽然它们都能用于初始化数据,但它们的实现方式和用途却有所不同。
首先,我们来讨论一下new和make的基本区别。
new是一个内建函数,它的作用是为指定的类型分配一片内存空间,并返回该类型的指针。简单来说,new只是做了一件事情,即分配内存。例如:
var p *int
p = new(int)
上述代码中,我们为int类型的变量p分配了一片内存空间,并把该内存空间的地址赋值给了变量p。
而make也是一个内建函数,它的作用是创建一个指定类型的对象,并返回该对象。简而言之,make做了两件事情:分配内存和初始化对象。我们可以这样使用make:
s := make([]int, 0, 10)
m := make(map[string]int)
上述代码中,我们分别使用make创建了一个int类型的切片和一个string到int的映射。
接下来,我们讨论一下new和make的适用场景。
new通常用于创建一个具体类型的指针,例如指针、数组、结构体等。我们来看一个示例:
type Person struct {
name string
}
func main() {
p := new(Person)
}
上述代码中,new用于创建了一个名为Person的结构体的指针p。由于new只会分配内存而不会进行初始化,p的字段name将被自动赋值为空字符串。
相比之下,make通常用于创建slice、map和channel类型,因为它们都是对应的引用类型。我们来看一个示例:
s := make([]int, 0, 10)
m := make(map[string]int)
c := make(chan int)
上述代码中,make分别创建了一个int类型的切片s、一个string到int的映射m和一个int类型的channel c。由于make会分配内存并进行初始化,我们可以直接使用它返回的对象,而不需要手动初始化。
最后,我们讨论一下new和make的底层实现。
new的底层实现其实很简单,它调用了runtime.new函数:
func new(Type) *Type {
var p unsafe.Pointer
return (*Type)(p)
}
可以看出,new只是声明了一个变量p,并将其转换成了对应类型的指针返回。
而make的底层实现稍微复杂一些,它的底层实现取决于具体的类型。以创建slice的make为例:
func make([]T, len, cap) []T {
// ... 省略其他代码
return tmp
}
可以看到,make函数在底层调用了runtime.makeslice函数,并将其返回。
综上所述,new和make都能用于初始化数据,但它们的实现方式和用途有所不同。new只是分配内存,适用于创建指针、数组、结构体等类型的对象;而make不仅分配内存,还会进行初始化,适用于创建slice、map和channel等引用类型的对象。在选择使用new还是make时,我们需要根据具体的类型和需求来决定。