面试题答案
一键面试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
函数中的container
的Pointer
字段。所以最后打印出的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
。