gonew和make的区别以及为什么new返回的是指针问题分析

Written by

in

文章目录
  • 在 Go 语言中,new 和 make 都是用于内存分配的内建函数,但它们有不同的用途和行为。
  • 以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。 您可能感兴趣的文章: Go语言中new与make的使用解读 Go语言中make和new的区别及说明 Golang中的new()和make()函数本质区别 Golan中 new() 、 make() 和简短声明符的区别和使用 浅析Golang中make和new的用法区别 Golang中make与new使用区别小结 详解golang中make与new的异同点和用法
  • 目录
    • Go 语言中 new 和 make 的区别
      • new 函数
      • make 函数
    • new 为什么要返回指针呢
      • 1. 明确表示分配在堆上
      • 2. 避免不必要的值拷贝
      • 3. 与零值初始化语义一致
      • 4. 与 make 区分明确
      • 5. 实际使用场景的需要
    • 总结

      在 Go 语言中,new 和 make 都是用于内存分配的内建函数,但它们有不同的用途和行为。

      new(T) 用于为值类型分配内存并返回指针:

      • 接受一个类型 T 作为参数
      • 返回一个指向新分配的零值 T 的指针 *T
      • 适用于所有值类型(包括结构体、数组等)
      p := new(int)   // p 是 *int 类型,指向一个零值的 int
      fmt.Println(*p) // 输出 0
      
      type Person struct {
          Name string
          Age  int
      }
      

      personPtr := new(Person) // 分配 Person 结构体的零值并返回指针

      make 专门用于创建 slice、map 和 channel 这三种引用类型:

      • 接受一个类型和可选的容量/长度参数
      • 返回已初始化的(非零值)T 类型(不是指针)
      • 只适用于 slice、map 和 channel
      s := make([]int, 10)     // 长度为10的切片
      m := make(map[string]int) // 初始化一个map
      c := make(chan int, 5)   // 缓冲大小为5的通道
      

      主要区别

      当需要初始化 slice、map 或 channel 时使用 make

      对于结构体,通常使用 &T{} 语法比 new 更常用

      // 通常这样创建结构体实例
      p := &Person{Name: "Alice", Age: 30}
      
      // 而不是
      p := new(Person)
      p.Name = "Alice"
      p.Age = 30
      

      返回指针可以明确表示这个值是在堆上分配的,而不是栈上。在 Go 中:

      • 栈上分配的值在函数返回后会被自动回收
      • 堆上分配的值由垃圾回收器管理
      • 通过返回指针,明确告诉使用者这个值会持续存在,不会被自动回收。

      如果 new 返回值而不是指针:

      v := new(MyStruct) // 假设 new 返回值
      funcThatTakesPointer(&v) // 需要显式取地址
      

      这样会导致额外的值拷贝。而返回指针可以直接传递,更高效。

      new 的语义是"分配并返回零值",如果返回值:

      v := new(int) // 假设返回 0
      

      那么就无法区分这是新分配的值还是字面量 0。返回指针 *int 则明确表示了这是一个新分配的值。

      Go 语言设计者刻意区分:

      • make 用于创建并初始化 slice/map/channel(返回已初始化的值)
      • new 用于分配内存并返回指针(强调内存分配)

      大多数需要 new 的场景都是需要指针的场景:

      // 常见用法
      var p *TreeNode
      p = new(TreeNode)
      
      // 如果 new 返回值,就需要写成
      var p TreeNode
      pp := &p
      // 这样反而更不直观
      

      返回值的设计问题

      如果 new 返回值:

      • 无法表示"分配新内存"的语义
      • 与结构体字面量初始化 T{} 难以区分
      • 需要指针时仍需额外取地址操作

      因此,返回指针是更合理的设计选择,它:

      • 明确表达了内存分配语义
      • 避免了不必要的拷贝
      • 与指针使用场景更匹配
      • 保持了语言设计的简洁性和一致性

      在 Go 中,如果你不需要指针,完全可以直接声明值类型变量或使用结构体字面量 T{},而不需要使用 new。

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。

      您可能感兴趣的文章:

      • Go语言中new与make的使用解读
      • Go语言中make和new的区别及说明
      • Golang中的new()和make()函数本质区别
      • Golan中 new() 、 make() 和简短声明符的区别和使用
      • 浅析Golang中make和new的用法区别
      • Golang中make与new使用区别小结
      • 详解golang中make与new的异同点和用法

      站内搜索