isayme / blog

https://blog.isayme.org
MIT License
10 stars 2 forks source link

Go: empty slice vs nil slice #35

Open isayme opened 5 years ago

isayme commented 5 years ago

Go Playgroud: https://play.golang.org/p/DNJ0Q9YrE14

var nilSlice []int emptySlice := []int{}

相同点

len(s)

len(nilSlice) == 0 // true len(emptySlice) == 0 // true

cap(s)

len(nilSlice) == 0 // true len(emptySlice) == 0 // true

不同点

s == nil ?

nilSlice == nil // true emptySlice == nil // false

json.Marshal

json.Marshal(nilSlice) // null json.Marshal(emptySlice) // []

json.Unmarshal

{} Unmarshal 后得到 nil slice; {"arr": null} Unmarshal 后得到 nil slice; // 如果是HTTP API, 则服务端无法知道客户端是未传arr字段还是传了一个null; {"arr": []} Unmarshal 后得到 empty slice;

如何检测是否是 nil slice

虽然 nilSlice == nil, 但换一种场景却无法判断:

var i interface{}
i = nilSlice

i == nil // false, 原因见: https://github.com/isayme/blog/issues/25

这里引入 stretchr/testify:IsNil 中的方法:

// IsNil 判定是否是 nil, 支持 pointer/channel/map/slice
func IsNil(v interface{}) bool {
    if v == nil {
        return true
    }

    value := reflect.ValueOf(v)
    kind := value.Kind()
    if kind >= reflect.Chan && kind <= reflect.Slice {
        return value.IsNil()
    }

    return false
}

参考资料