MST

星途 面试题库

面试题:Go语言中函数调用惯例之参数传递

在Go语言里,函数调用时参数传递遵循值传递的惯例。请描述一下当传递一个结构体类型参数时,在函数调用过程中内存是如何分配和使用的?举例说明如果结构体中包含指针字段,值传递会对指针字段产生什么影响。
28.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

1. 结构体参数值传递时内存分配与使用

在Go语言中,当函数调用传递结构体类型参数时,会在栈上为该结构体参数分配一块新的内存空间,并将调用函数处传递的结构体的值完整地复制到这块新的内存空间中。

例如:

package main

import "fmt"

type Point struct {
    X int
    Y int
}

func printPoint(p Point) {
    fmt.Printf("Point in function: X = %d, Y = %d\n", p.X, p.Y)
}

func main() {
    p := Point{1, 2}
    printPoint(p)
}

在上述代码中,main函数中的p结构体在栈上有自己的内存空间。当调用printPoint函数时,会在printPoint函数的栈帧上为p参数分配一块新的内存空间,并将main函数中p的值复制到这块新空间。

2. 结构体包含指针字段时值传递的影响

当结构体中包含指针字段时,值传递依然是将结构体的值(包括指针的值)进行复制。这意味着在被调用函数中,结构体的指针字段指向的是与调用函数中结构体指针字段相同的内存地址。

例如:

package main

import "fmt"

type Data struct {
    Value int
}

type Container struct {
    Pointer *Data
}

func modifyContainer(c Container) {
    newData := Data{100}
    c.Pointer = &newData
}

func main() {
    data := Data{42}
    container := Container{&data}
    modifyContainer(container)
    fmt.Printf("Value in main: %d\n", container.Pointer.Value)
}

在上述代码中,main函数中container结构体的Pointer字段指向data。当调用modifyContainer函数时,虽然container结构体被值传递复制到函数栈帧,但复制的指针字段仍然指向原来的data。在modifyContainer函数中重新赋值c.Pointer,只会影响函数内部的c,不会影响main函数中的containerPointer字段。所以最后打印出的Value in main依然是42

如果要在被调用函数中修改调用函数中结构体指针字段指向的内容,可以传递结构体指针,例如:

package main

import "fmt"

type Data struct {
    Value int
}

type Container struct {
    Pointer *Data
}

func modifyContainer(c *Container) {
    newData := Data{100}
    c.Pointer = &newData
}

func main() {
    data := Data{42}
    container := Container{&data}
    modifyContainer(&container)
    fmt.Printf("Value in main: %d\n", container.Pointer.Value)
}

此时,modifyContainer函数接收的是Container结构体指针,对c.Pointer的修改会影响到main函数中的container,最后打印出100