MST

星途 面试题库

面试题:Go语言defer在函数返回值场景下的陷阱分析

以下是一段Go语言代码: ```go package main import "fmt" func test() (result int) { defer func() { result++ }() return 1 } ``` 请回答函数test的返回值是多少,并详细说明defer对函数返回值修改的原理以及这里面可能存在的陷阱。
28.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 函数test的返回值: 函数test的返回值是2
  2. defer对函数返回值修改的原理
    • 在Go语言中,当函数执行到return语句时,会先计算返回值并将其存储到一个临时变量(假设为tmp)中。这里return 1会先把1赋值给result(因为result是具名返回值)。
    • 然后,函数会执行所有的defer语句。defer语句中的函数会在函数结束前(包括return语句之后)执行。这里defer func() { result++ }()会对具名返回值result进行自增操作,使得result的值变为2
    • 最后,函数返回存储在临时变量(这里就是result本身,因为具名返回值优化)中的值,所以返回值为2
  3. 可能存在的陷阱
    • 非具名返回值的情况:如果返回值不是具名的,例如func test() int { var res int; defer func() { res++ }(); return 1 },这里res是函数内部的局部变量,defer语句修改的res不会影响到返回值,函数仍然返回1。因为非具名返回值在return时计算的值就直接返回了,defer修改的局部变量不会改变返回值。
    • 多层嵌套defer:如果有多层嵌套的defer语句,要注意执行顺序。defer语句是后进先出(LIFO)的顺序执行,复杂的嵌套可能导致逻辑难以理解和调试。例如func test() (result int) { defer func() { result++ }(); defer func() { result = result * 2 }(); return 1 },这里先执行内层deferresult变为2,再执行外层deferresult变为3,返回值为3
    • defer中修改外部变量:如果defer函数中修改的变量是在函数外部定义的,可能会导致意外的行为。例如func test() int { var globalVar int; defer func() { globalVar++ }(); return 1 }defer修改的globalVar虽然不会影响返回值,但会改变外部变量的值,在多线程环境下可能引发数据竞争等问题。