编程Go开发者

解释Go语言内置函数make的工作特点:何时需要它,如何处理map、slice和channel的切片初始化?由于错误使用make和new会出现哪些错误?

用 Hintsage AI 助手通过面试

回答

在Go语言中,make函数专门用于初始化slicemapchannel类型的对象。它分配所需的数据结构,并返回一个可以使用的对象(不是指针!)。

示例:

s := make([]int, 5, 10) // 长度为5,容量为10的切片 m := make(map[string]int) // 空map ch := make(chan int, 2) // 容量为2的缓冲通道

细节:

  • 对于slice,参数:长度(len)和(可选)容量(cap)。
  • 对于mapchan——只有(可选的)容量(初始大小/缓冲)。
  • make函数返回的对象已经初始化,准备好使用。
  • 对于其他类型(struct,array),不使用make,它们通过字面量或new进行初始化(new返回的是零值的指针)。

new的比较:

  • new(T)返回*T,所有字段均为零。
  • make(T)仅返回三种类型的Tslicemapchan

陷阱问题

可以通过new而不是make获取工作中的map吗?

m := new(map[string]int) (*m)["a"] = 1 // 会发生什么?

许多人认为这是正确的,但会在运行时引发panic:assignment to entry in nil map。因为在变量*m中是nil!

**正确的做法:**使用make

m := make(map[string]int) m["a"] = 1 // 好的

由于不熟悉主题细节而导致的真实错误示例


故事

在一个微服务中,用var cache map[string]interface{}创建map而未初始化make,导致在写入时出现panic,生产环境中的stack trace令人困惑。只有在分析代码后发现问题:map为nil。


故事

在编写数据管道时,忘记了通道的缓冲,使用make(chan int)创建,结果导致goroutine卡住,等待读取,而预期是异步交换。这个错误只有在大规模测试时才被发现。


故事

在一个通过new进行初始化的项目中,一些开发人员尝试使用new([]int)而不是make([]int, 10),最终得到了一个指向nil切片的指针,并在第一次写入时发生运行时panic。