make和new的区别

在Go语言中,makenew都是用于内存分配的,但它们之间的主要区别在于它们用于分配不同类型的内存。

new

new是一个内建函数,用于为指定类型分配内存并返回指向它的指针。new分配的内存会被初始化为零值。new只接受一个参数,即类型,而不是值。它返回一个指向新分配的类型零值的指针。

示例:

package main  
  
import "fmt"  
  
type Person struct {  
    Name string  
    Age  int  
}  
  
func main() {  
    // 使用 new 为 Person 类型分配内存  
    p := new(Person)  
    fmt.Println(p) // 输出: &{ 0}  
  
    // 可以通过指针访问并修改字段的值  
    p.Name = "Alice"  
    p.Age = 30  
    fmt.Println(p) // 输出: &{Alice 30}  
}

在上面的例子中,new(Person)Person类型分配了内存,并返回了一个指向该内存的指针。然后,我们通过该指针修改了Person字段的值。

疑问:

既然是返回的是指针,修改字段值的时候,为什么不是(*p).Name呢?文心一言给的答案是:

在Go语言中,当使用new函数为结构体分配内存时,返回的是一个指向该结构体的指针。由于Go语言支持指针的自动解引用(也被称为指针的隐式解引用或指针方法的接收者),因此在访问结构体的字段时,可以直接通过指针来访问,而不需要显式地解引用指针。

示例:

type Person struct {  
    Name string  
    Age  int  
}
使用new函数分配内存后:
p := new(Person)
此时p是一个指向Person结构体的指针。由于Go的语法糖,当你通过p.Name来访问Name字段时,Go会自动将p解引用为它所指向的Person实例,然后访问其Name字段。

这种自动解引用的行为是Go语言设计的一部分,它使得指针的使用更加简洁和直观。当然,如果你需要显式地解引用指针,可以使用(*p).Name的形式,但这并不是必须的,因为p.Name已经足够了。

下面是一个完整的例子,展示了如何使用new为结构体分配内存,并直接通过指针访问和修改结构体的字段:
package main  
  
import "fmt"  
  
type Person struct {  
    Name string  
    Age  int  
}  
  
func main() {  
    // 使用 new 为 Person 分配内存  
    p := new(Person)  
  
    // 直接通过指针访问和修改字段的值  
    p.Name = "Alice"  
    p.Age = 30  
  
    // 打印修改后的值  
    fmt.Println(p.Name) // 输出: Alice  
    fmt.Println(p.Age)  // 输出: 30  
  
    // 如果需要显式解引用,可以这样写,但通常不是必须的  
    fmt.Println((*p).Name) // 输出: Alice  
    fmt.Println((*p).Age)  // 输出: 30  
}

在这个例子中,你可以看到p.Name和p.Age的用法与(*p).Name和(*p).Age是完全等效的。通常情况下,我们会选择使用更简洁的p.Name和p.Age形式。

make

make函数用于初始化并返回引用类型的对象(如切片、映射和通道)。它返回一个已经初始化的(非零)引用类型的值,而不是指针。make接受类型、长度和容量(对于切片和通道)作为参数。

package main  
import "fmt"  
func main() {  
    // 使用 make 创建一个切片  
    s := make([]int, 5)  
    fmt.Println(s) // 输出: [0 0 0 0 0]  
  
    // 使用 make 创建一个映射  
    m := make(map[string]int)  
    fmt.Println(m) // 输出: map[]  
  
    // 使用 make 创建一个通道  
    c := make(chan int)  
    fmt.Println(c) // 输出: (chan int)(0xc00000e020)  
}

在上面的例子中,make([]int, 5)创建了一个长度为5的切片,所有元素都被初始化为零值(对于int类型,零值是0)。make(map[string]int)创建了一个空的映射,make(chan int)创建了一个无缓冲的通道。

总结:

  • new用于为指定类型分配内存并返回指向它的指针。它返回的是一个指向零值的指针。
  • make用于初始化并返回引用类型的对象(如切片、映射和通道)。它返回的是一个已经初始化的引用类型的值,而不是指针。

在大多数情况下,你会使用make来创建切片、映射和通道,而使用new的情况相对较少。对于结构体和其他非引用类型,如果你需要动态分配内存并返回指针,那么可以使用new。但通常,直接使用类型字面量(如p := Person{})来创建变量会更常见。

 

 

posted @ 2024-04-03 09:56  羊脂玉净瓶  阅读(6)  评论(0)    收藏  举报