slice 指向数组的窗口
- 假设 planets 是一个数组,那么 planets[0:4] 就是一个切片,它切分出了数组里前 4 个元素。
- 切分数组不会导致数组被修改,它只是创建了指向数组的一个窗口或视图,这种视图就是 slice 类型。

切分数组
- Slice 使用的是半开区间
例如 planets[0:4],包含索引 0、1、2、3 对应的元素,不包括索引 4 对应的元素。
package mainimport "fmt"func main() { planets := [...]string{ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", } terrestrial := planets[0:4] gasGiants := planets[4:6] iceGiants := planets[6:8] fmt.Println(terrestrial, gasGiants, iceGiants) fmt.Println(gasGiants[0]) giants := planets[4:8] gas := giants[0:2] ice := giants[2:4] fmt.Println(giants, gas, ice) iceGiantsMarkII := iceGiants iceGiants[1] = "Poseidon" fmt.Println(planets) fmt.Println(iceGiants, iceGiantsMarkII, ice)}
slice 的默认索引
- 忽略掉 slice 的起始索引,表示从数组的起始位置进行切分;
- 忽略掉 slice 的结束索引,相当于使用数组的长度作为结束索引。
- 注意:slice 的索引不能是负数。
- 如果同时省略掉起始和结束索引,那就是包含数组所有元素的一个 slice。
- 切分数组的语法也可以用于切分字符串
- 切分字符串时,索引代表的是字节数而非 rune 的数。
package mainimport "fmt"func main() { planets := [...]string{ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", } terrestrial := planets[:4] gasGiants := planets[4:6] iceGiants := planets[6:] fmt.Println(terrestrial, gasGiants, iceGiants) allPlanets := planets[:] fmt.Println(allPlanets) colonized := terrestrial[2:] fmt.Println(colonized)}
slice 的复合字面值
- Go 里面很多函数都倾向于使用 slice 而不是数组作为参数。
- 想要获得与底层数组相同元素的 slice,那么可以使用 [:] 进行切分
- 切分数组并不是创建 slice 唯一的方法,可以直接声明 slice:
package mainimport "fmt"func main() { dwarfArray := [...]string{"Ceres", "Pluto", "Haumea", "Makemake", "Eris"} dwarfSlice := dwarfArray[:] dwarfs := []string{"Ceres", "Pluto", "Haumea", "Makemake", "Eris"} fmt.Println(dwarfSlice, dwarfs) fmt.Printf("array %T\n", dwarfArray) fmt.Printf("slice %T\n", dwarfs)}
切片的威力
package mainimport ( "fmt" "strings")// hyperspace removes the space surrounding worldsfunc hyperspace(worlds []string) { for i := range worlds { worlds[i] = strings.TrimSpace(worlds[i]) }}func main() { planets := []string{" Venus ", "Earth ", " Mars"} hyperspace(planets) fmt.Println(strings.Join(planets, ""))}
带有方法的切片
- 在 Go 里,可以将 slice 或数组作为底层类型,然后绑定其它方法。
package mainimport ( "fmt" "sort")func main() { planets := []string{ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", } sort.StringSlice(planets).Sort() fmt.Println(planets)}
作业题
- 编写一个程序:
- 它通过给字符串 slice 中所有的行星加上“New ”前缀来完成行星的地球化处理,然后使用该程序对 Mars、Uranus、Neptune 实行地球化
- 必须使用 planets 类型,并为之实现相应的 terraform 方法。
package mainimport "fmt"// Planets attaches methods to []string.type Planets []stringfunc (planets Planets) terraform() { for i := range planets { planets[i] = "New " + planets[i] }}func main() { planets := []string{ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", } Planets(planets[3:4]).terraform() Planets(planets[6:]).terraform() fmt.Println(planets)}