MST

星途 面试题库

面试题:Go 中 Gomake 与 new 在结构体嵌套场景下的差异

假设有一个结构体 A 嵌套了结构体 B,结构体 B 又包含一个切片字段。请阐述使用 Gomake 和 new 对结构体 A 进行初始化时,结构体 B 及其切片字段的初始化过程、内存布局会有怎样的不同,并且写出相应的代码来展示这种差异。
37.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 使用 new 初始化
    • 初始化过程new 函数会为结构体 A 分配内存,并将其所有字段初始化为零值。对于嵌套的结构体 B,也会被初始化为零值,其切片字段会被初始化为 nil
    • 内存布局new 分配的内存是连续的,结构体 A 的内存紧接着其嵌套的结构体 B 的内存,切片字段在结构体 B 内存布局中有相应的位置,但因为是 nil,实际数据部分还未分配。
    • 示例代码
package main

import "fmt"

type B struct {
    Slice []int
}

type A struct {
    InnerB B
}

func main() {
    a := new(A)
    fmt.Printf("a.InnerB.Slice: %v (type: %T)\n", a.InnerB.Slice, a.InnerB.Slice)
}
  1. 使用 make 初始化(注:Go 中没有 Gomake,猜测这里是 make 用于初始化切片等复合类型)
    • 初始化过程make 不能直接用于初始化结构体 A,但可以用于初始化结构体 B 中的切片字段。如果在初始化结构体 A 后手动使用 make 初始化 B 中的切片字段,会为切片分配内存并初始化其容量和长度。
    • 内存布局:结构体 AB 依然是连续内存布局,但是通过 make 初始化的切片,其实际数据部分会在堆上另外分配一块连续的内存,结构体 B 中的切片字段会持有指向这块数据内存的指针,以及长度和容量信息。
    • 示例代码
package main

import "fmt"

type B struct {
    Slice []int
}

type A struct {
    InnerB B
}

func main() {
    a := A{}
    a.InnerB.Slice = make([]int, 0, 5)
    fmt.Printf("a.InnerB.Slice: %v (type: %T, len: %d, cap: %d)\n", a.InnerB.Slice, a.InnerB.Slice, len(a.InnerB.Slice), cap(a.InnerB.Slice))
}