MST

星途 面试题库

面试题:Go语言中函数参数传递值类型与引用类型的陷阱差异

在Go语言中,分别阐述值类型(如int、float等)和引用类型(如slice、map、pointer等)作为函数参数传递时,可能会遇到哪些不同的陷阱?请通过代码示例说明。
43.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

值类型作为函数参数传递的陷阱

  1. 值拷贝开销:值类型传递时会进行值拷贝,如果值类型数据较大,会消耗较多的内存和时间。
  2. 函数内修改不影响原值:函数内对值类型参数的修改,不会影响到调用者传入的原始值。
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 的值并未改变。

引用类型作为函数参数传递的陷阱

  1. 空引用未初始化:如果引用类型(如 slicemap)作为参数传递,但在函数内未初始化就使用,会导致运行时错误。
  2. 误修改共享数据:由于引用类型传递的是地址,函数内对引用类型数据的修改会影响到调用者传入的原始数据,可能会引发意想不到的结果。
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 指针,会导致运行时错误。