无法返回nil,但是slice的值为零

I am having the case in which a function with the following code:

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

is returning []string(nil) instead of nil. At first, I thought that perhaps returning nil in a function with a particular return type would just return an instance of a zero-value for that type. But then I tried a simple test and that is not the case.

Does anybody know why would nil return an empty string slice?

Nil is not a type. It is a description of the zero value for maps, chans, pointers, functions, slices, and interfaces.

When you put "nil" in your program, go gives it a type depending on the context. For the most part, you never need to explicitly type your nil. This is no exception, the compiler knows it must be a []string(nil) because the type returned is []string.

A nil string slice is a slice with no backing array and a length/capacity of zero. You may compare it to the literal "nil" and can get its length and capacity. It is a []string, just empty. If you wish to have an empty []string that is not nil, return []string{}. This creates a backing array (of length zero) and makes it no longer equivalent to nil.

I think maybe you are being confused by the output of 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
", result)
    fmt.Printf("result = %v
", result == nil)
}

Which produces

result = []
result = true

So I think the output really is nil

I believe I know what's going on. The assert library I am using (github.com/bmizerany/assert) is using internally a reflect.DeepEqual.

The return value of func halfMatch(text1, text2 string) []string is always of type []string, but if it returns nil and is compared to a nil value via the == operator, it will return true. However, if reflect.DeepEqual is used, the type will matter and it won't consider both values the same.

playgound link with the test

Go will return an enpty slice if condition is true.

There is a problem with your "test" because if you try to compare [] with nil, you get true. I have modified your test to show you what I mean

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
}