【问题标题】:strange behaviour while same variable as input and output of function奇怪的行为,而与函数的输入和输出相同的变量
【发布时间】:2018-10-09 02:26:27
【问题描述】:

对于下面的代码,它似乎进入了死循环。 在s, err := minusOne(s) 之后,s 根据日志信息被缩短。 但是之前的减号日志显示它从未改变过。

func minusOne(s string) (string, error) {
    if len(s) >= 0 {
        return s[1:], nil
    }
    return "", nil
}

func TestStr(t *testing.T) {
    s := "hello world"
    for {
        log.Println("before minus", s)
        s, err := minusOne(s)
        log.Println("after minus", s)
        if err == nil && len(s) == 0 {
            break
        }
    }
}

如果我稍微改变一下,它就会像预期的那样工作。

s1, err := minusOne(s)
s = s1

或者如果我删除了减号函数中返回的错误,它也可以工作。

s = minusOne(s)

我真的无法理解。 有人可以帮忙吗?

【问题讨论】:

    标签: string go variable-assignment


    【解决方案1】:

    在每次迭代中,您声明名为 serr 的新变量:

    s, err := minusOne(s)
    

    它们的作用域只是当前的迭代,所以上面的行继续使用在循环外声明的相同的s 变量。来自Declarations and scope Go 规范的一部分:

    Go 的词法范围使用块:

    1. 在函数内声明的常量或变量标识符的范围从 ConstSpec 或 VarSpec(短变量声明的 ShortVarDecl)的末尾开始,到最里面的包含块的末尾结束。

    要修复它,你需要使用赋值:

    var err error
    for {
        // ...
        s, err = minusOne(s)
        // ...
    }
    

    【讨论】:

      【解决方案2】:

      您正在使用简短的 var 声明 :=。您必须注意这一点。

      for 循环内,您将创建两个新变量err,还有s(在for 循环内有一个新范围)。如果您在相同的范围内这样做,这将不是问题。

      您可以像这样简单地将err 提取到预先声明的变量中:

      var err error
      s, err = minusOne(s)
      

      【讨论】:

        【解决方案3】:

        不要在 for 循环中使用 s,:= 将添加一个新的本地变量。只需将 s in for loot 重命名为 s1。您还可以声明一个外部 for 循环并将 := 替换为 =

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-21
          • 2015-06-17
          • 1970-01-01
          • 2023-04-09
          • 2010-12-22
          • 2013-02-08
          相关资源
          最近更新 更多