面试题答案
一键面试值类型作为函数参数传递的陷阱
- 值拷贝开销:值类型传递时会进行值拷贝,如果值类型数据较大,会消耗较多的内存和时间。
- 函数内修改不影响原值:函数内对值类型参数的修改,不会影响到调用者传入的原始值。
package main
import "fmt"
func modifyValue(num int) {
num = num + 10
fmt.Printf("函数内 num 修改后的值: %d\n", num)
}
func main() {
num := 5
modifyValue(num)
fmt.Printf("函数外 num 的值: %d\n", num)
}
在上述代码中,modifyValue
函数对 num
进行了修改,但函数外 num
的值并未改变。
引用类型作为函数参数传递的陷阱
- 空引用未初始化:如果引用类型(如
slice
、map
)作为参数传递,但在函数内未初始化就使用,会导致运行时错误。 - 误修改共享数据:由于引用类型传递的是地址,函数内对引用类型数据的修改会影响到调用者传入的原始数据,可能会引发意想不到的结果。
package main
import "fmt"
func modifySlice(slice []int) {
if slice == nil {
slice = make([]int, 0)
}
slice = append(slice, 10)
fmt.Printf("函数内 slice 修改后的值: %v\n", slice)
}
func main() {
var slice []int
modifySlice(slice)
fmt.Printf("函数外 slice 的值: %v\n", slice)
}
在上述代码中,modifySlice
函数中如果不初始化 slice
直接 append
会报错。并且如果 slice
已初始化,函数内的修改会影响到函数外的 slice
。
package main
import "fmt"
func modifyMap(m map[string]int) {
if m == nil {
m = make(map[string]int)
}
m["key"] = 20
fmt.Printf("函数内 map 修改后的值: %v\n", m)
}
func main() {
var m map[string]int
modifyMap(m)
fmt.Printf("函数外 map 的值: %v\n", m)
}
同样,对于 map
,如果不初始化直接操作会报错,且初始化后函数内修改会影响到函数外。
指针作为参数传递时,如果对指针指向的值进行修改,会影响到原始值。
package main
import "fmt"
func modifyPointer(ptr *int) {
if ptr != nil {
*ptr = *ptr + 10
fmt.Printf("函数内指针指向的值修改后: %d\n", *ptr)
}
}
func main() {
num := 5
ptr := &num
modifyPointer(ptr)
fmt.Printf("函数外 num 的值: %d\n", num)
}
这里函数内通过指针修改了值,函数外 num
的值也相应改变。如果传入 nil
指针,会导致运行时错误。