下面代码填空cc处可以填入哪个选项? 且描述一下填入后运行的结果
package main
import "fmt"
func main() {
var s1 []int
var s2 = []int{}
_, _ = s1, s2
if 填空 == nil {
fmt.Println("yes nil")
} else {
fmt.Println("no nil")
}
}
- A. s1
- B. s2
- C. s1、s2 都可以
- D. 以上都不可以
C 在线运行
package main
import "fmt"
func main() {
var s1 []int
var s2 = []int{}
_, _ = s1, s2
if s1 == nil {
fmt.Println("yes nil")
} else {
fmt.Println("no nil")
}
if s2 == nil {
fmt.Println("yes nil")
} else {
fmt.Println("no nil")
}
}
//yes nil
//no nil
切片(Slice) nil 与空切片
在 Go 文档 - Slice types 中有这样一段描述:
The value of an uninitialized slice is nil.
如果一个切片没有被初始化,它的值就是nil。
根据这段描述,我们可以得出以下结论:
1. 填入 s1 的情况
s1是通过var s1 []int声明的,这是一个未初始化的切片,其值为nil。- 因此,程序会进入
"yes nil"分支。
2. 填入 s2 的情况
s2是通过var s2 = []int{}声明的,这是一个已初始化的空切片。- 虽然它的长度为 0,但它并不是
nil,而是指向了一个底层数组(即使该数组的空间为 0)。 - 因此,程序会进入
"no nil"分支。
代码验证
以下代码验证了 s1 和 s2 的底层数据指针:
package main
import (
"fmt"
"unsafe"
)
func main() {
var s1 []int
var s2 = []int{}
fmt.Println("s1 底层 Data 值为", unsafe.SliceData(s1)) // <nil>
fmt.Println("s2 底层 Data 值为", unsafe.SliceData(s2)) // 0x572380(具体地址可能不同)
}
补充
切片之间不能直接使用 == 或 != 进行比较