卡码笔记-最强八股文
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
  • 本栏必读

    • Go语言面试题专栏介绍
  • 语言基础

    • Go有哪些基础数据类型
    • slice和array区别/slice和map区别
    • 值类型和引用类型的区别
    • new和make的区别
      • 简要回答
      • 详细回答
      • 知识图解
      • 知识扩展
    • 接口是什么?如何实现接口
    • struct tag有什么作用
    • defer的执行顺序
    • 多层defer发生panic还会执行吗
    • 反射原理与谨慎使用场景
    • panic和recover的作用及使用场景
  • 内存管理

  • 并发编程

  • 底层原理

# Go语言中new和make的区别是什么?分别用于什么场景?

注意使用 new 时仅分配内存并返回指针,未初始化底层数组。

以下为知识星球 (opens new window)录友分享的得物后端面试问题:“Go语言中new和make有什么区别?分别用于什么场景?”(下文知识框架部分提供了图例)

# 简要回答

在 Go 语言中,new 和 make 都是用于内存分配的内建函数,但它们的设计目的和适用场景有着根本的不同。

new 只分配内存并清零,返回一个指向该类型零值的指针,适用于基本类型和结构体(struct);

而 make 不仅分配内存,还会进行初始化,专门用于创建切片(slice)、映射(map)和通道(channel)这三种内建的引用类型,并返回一个已初始化的、可直接使用的值,而非指针。

# 详细回答

在 Go 语言中,new 和 make 的根本区别在于用途与返回值。

new 是一个通用内存分配器,会在堆上分配一块足够容纳类型 T 的内存空间,并将这块内存的所有位设置为零,最后返回指向这块内存的指针 *T。

  • 对于值类型(如基本类型、结构体),会得到一个指向有效零值的指针。
  • 对于引用类型(slice, map, channel),返回的是指向 nil 值的指针。例如,new([]int) 返回一个类型为 *[]int 的指针,但其指向的切片本身是 nil,无法直接使用。

而make 是一个专用的构造函数,仅用于切片、映射和通道这三种内建的引用类型。它会执行复杂初始化并直接返回一个已初始化、立即可用的值 ,而非指针。

  • 对于切片:make([]T, len, cap) 会分配一个底层数组(容量为 cap),并创建一个切片头(包含指向数组的指针、长度和容量)来管理这块数组。
  • 对于映射:make(map[K]V) 会初始化一个哈希表结构,包括创建桶等内部数据结构,使其可以立即接收键值对。
  • 对于通道:make(chan T, size) 会创建通道所需的环形缓冲区以及同步用的互斥锁等结构,使其能够进行协程间的通信。

因此,选择使用哪个函数取决于具体场景:

当需要立即可用的切片、映射或通道时,必须使用 make。当需要获取一个指向某类型零值的指针时,则使用 new。

# 知识图解

image

使用场景对比:

image

# 知识扩展

# Go的零值机制

在Go中,声明一个变量但未显式初始化时,它会自动被初始化为该类型的零值。

  • 值类型(如 int , struct)的零值是真切的零(如0, false)。
  • 引用类型(如slice , map , chan)的零值是 nil。

这就解释了为什么对于切片、映射和通道,我们通常用 make 而不是直接使用 var 声明后的零值?

  • var s []int 声明的是一个 nil 切片。可以成功对它调用 append 函数,因为 append 会处理 nil 切片的情况。但如果尝试 s[0] = 1,会触发panic。
  • s := make([]int, 0) 创建的是一个已初始化的、非nil的空切片,它拥有完整的底层数据结构,可以直接安全地进行索引操作。

# 面试官可能会追问:

Q1:除了返回类型,new 和 make 在底层内存分配上有何不同?

A1:

  • new 仅调用 runtime.newobject 分配一块清零的内存,适用于所有类型,但不初始化复杂数据结构。
  • make 专用于 slice、map、channel,底层会调用类型特定的构造函数(如 runtime.makeslice、runtime.makemap),不仅分配内存,还初始化其内部结构(如切片的底层数组、map 的哈希桶、channel 的缓冲区),使其立即可用。

Q2:Go的内存分配器如何支持 new 和 make的高效运作?

A2:Go采用多级缓存架构(类似 TCMalloc):

  1. mcache:每个P(处理器)的本地缓存,无锁分配小对象(<32KB)。
  2. mcentral:全局中央缓存,按对象大小分类管理内存块(mspan)。
  3. mheap:堆管理器,直接向操作系统申请大内存。

new 和 make 创建小对象时,优先从 mcache 快速分配;大对象(>32KB)则直接由 mheap 处理。这种设计减少锁竞争,提升并发性能。


如果你在学习、求职的路上,需要有个高手全程带你,欢迎报名:

  • 卡码C++训练营 (opens new window)
  • 卡码Java、Go训练营 (opens new window)
  • 卡码大模型应用开发训练营 (opens new window)
Last Updated: 4/29/2026, 3:26:47 PM

← 值类型和引用类型的区别 接口是什么?如何实现接口 →

评论

验证登录状态...

侧边栏
夜间
卡码简历
代码随想录
卡码投递表🔥
2026群
添加客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记
鼓励/支持/赞赏Carl
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪