【问题标题】:Can't return nil, but zero value of slice不能返回零,但切片的值为零
【发布时间】:2012-12-20 09:58:26
【问题描述】:

我遇到的情况是一个函数的代码如下:

func halfMatch(text1, text2 string) []string {
    ...
    if (condition) {
         return nil // That's the final code path)
    }
    ...
}

返回 []string(nil) 而不是 nil。起初,我认为在具有特定返回类型的函数中返回 nil 可能只会返回该类型的零值实例。但后来我尝试了一个简单的test,但事实并非如此。

有人知道为什么nil 会返回一个空字符串切片吗?

【问题讨论】:

  • 您的测试用例按预期工作并返回 nil。您能否生成一个行为类似于您遇到问题的代码的测试用例?您的逻辑可能有错误并返回其他地方。
  • 我会努力把它变成一个更好的测试用例,但是在我相信返回nilreturn之前,我有一个Println被打印出来,所以一定是这样return 声明。

标签: go


【解决方案1】:

Nil 不是类型。它是对映射、通道、指针、函数、切片和接口的零值的描述。

当你在你的程序中添加“nil”时,go 会根据上下文给它一个类型。在大多数情况下,您永远不需要显式键入您的 nil。这也不例外,编译器知道它必须是 []string(nil),因为返回的类型是 []string。

零字符串切片是没有后备数组且长度/容量为零的切片。您可以将其与文字“nil”进行比较,并可以得到它的长度和容量。它是一个 [] 字符串,只是空的。如果您希望有一个不为 nil 的空 []string,请返回 []string{}。这会创建一个后备数组(长度为零)并使其不再等价于 nil。

【讨论】:

    【解决方案2】:

    我相信我知道发生了什么。我正在使用的断言库 (github.com/bmizerany/assert) 在内部使用 reflect.DeepEqual

    func halfMatch(text1, text2 string) []string 的返回值始终是[]string 类型,但如果它返回nil 并通过== 运算符与nil 值进行比较,它将返回true。但是,如果使用reflect.DeepEqual,则类型很重要,并且不会认为两个值相同。

    playgound link with the test

    【讨论】:

    • 我认为你是对的。由于DeepEqual 有两个interface{} 值,reflect.DeepEqual(test1(""), nil) 将导致DeepEqual 得到[]string{}(零字符串切片)和interface{}(零接口值),这将由于类型不匹配而失败。
    【解决方案3】:

    我想你可能对 print 的输出感到困惑。 (playground link)

    package main
    
    import "fmt"
    
    func f() []string {
        return nil // That's the final code path)
    }
    func main() {
        result := f()
        fmt.Printf("result = %v\n", result)
        fmt.Printf("result = %v\n", result == nil)
    }
    

    哪个产生

    result = []
    result = true
    

    所以我认为输出真的是nil

    【讨论】:

    • 其实我的断言失败了:assert.go:24: ! []string(nil) != nil
    【解决方案4】:

    如果条件为真,Go 将返回一个 enpty 切片。

    您的“测试”有问题,因为如果您尝试将 [] 与 nil 进行比较,您会得到正确的结果。 我已经修改了你的测试来告诉你我的意思

    package main
    import "fmt"
    
    func main() {
        //fmt.Println(test1("") == nil)  
        fmt.Println(test1("")) // prints [] 
    }
    
    func test1(text1 string) []string {
        if len(text1) > 0 {
            return []string{text1}
        }
        return nil
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-08
      • 2021-08-12
      • 2011-11-07
      • 2016-01-30
      • 2012-10-07
      相关资源
      最近更新 更多