golang make 0 length slice and re-slicing slice not as expected

huangapple go评论131阅读模式
英文:

golang make 0 length slice and re-slicing slice not as expected

问题

我看到这段代码感到困惑,请帮我解释一下。

这段代码的作用是:

package main

import "fmt"

func main() {
	s := make([]int, 0, 10)
	s1 := s[0:1]
	s1[0] = 1
	println("-----")
	fmt.Println(s1, len(s1), cap(s1)) //[1] 1 10
	fmt.Println(s, len(s), cap(s))    //[] 0 10
	fmt.Println(s, s[0:10])           // [] [1 0 0 0 0 0 0 0 0 0]
}

上述程序可以完美执行,但打印的值不符合我的预期,我有两个问题:

  • 为什么在 fmt.Println(s1, len(s1), cap(s1))fmt.Println(s, len(s), cap(s)) 中,s1 的打印值是 [1],而 s 的打印值是 []。我认为 s1 的值应该等于 s 的值,都是 [1]。

  • 为什么 s[0:10] 可能打印出 [1 0 0 0 0 0 0 0 0 0],而 s 打印的是 []。我认为 s[0:10] 是对 s 进行重新切片,如果 s 是 [],那么 s[0:10] 也应该是 []。

英文:

I saw this code feel confusing,please help me explain.

the code:

package main

import "fmt"

func main() {
	s := make([]int, 0, 10)
	s1 := s[0:1]
	s1[0] = 1
	println("-----")
	fmt.Println(s1, len(s1), cap(s1)) //[1] 1 10
	fmt.Println(s, len(s), cap(s))    //[] 0 10
	fmt.Println(s, s[0:10])           // [] [1 0 0 0 0 0 0 0 0 0]
}

The above program can be executed perfectly,While print value is not meet my expectations,I have two questions:

  • why s1 print value is: [1], while s print value is [] in the fmt.Println(s1, len(s1), cap(s1)) and fmt.Println(s, len(s), cap(s)). I think s1 value is equal to s value is [1].

  • why s[0:10] may print [1 0 0 0 0 0 0 0 0 0], while s print []. I think s[0:10] is re-slice of s,if s is [], s[0:10] is [] too.

答案1

得分: 1

  • s1 打印出 [1],因为它是一个长度为1的切片,并且在这个长度内有元素1。它的长度为1,是因为它是从 s 的索引 01 的切片。因此,s1 := s[0:1]
  • s 打印出 [],因为它是一个长度为0的切片。当长度为0时,没有值可以显示,所以在方括号中没有任何内容。它的长度为0是因为在 make 函数调用中指定了长度为0。在使用 make 创建切片时,第二个参数是切片的长度。
  • s[0:10] 可能打印出 [1 0 0 0 0 0 0 0 0 0],因为可以将现有的切片重新切片为其整个底层数组的容量,而不仅仅是长度。由于重新切片从 010,它将包含10个值(切片的第二个边界是不包含的)。这就是为什么在打印输出中看到了所有10个值。
  • 作为额外的说明,s[0:10] 不能是 [],因为这意味着你指定了一个长度为10的切片,但返回的却是一个长度为0的切片。在 Go 语言中,切片 s[a:b] 的长度始终为 b - a。如果这不可能,程序将会引发错误。它不会给你一个其他长度的切片。请参阅语言规范中关于这些规则的解释:https://go.dev/ref/spec#Slice_expressions
英文:
  • s1 prints [1] because it is a slice of length 1, and it has the element 1 within that length. It is length 1 because it is a slice of s from 0 to 1. Hence, s1 := s[0:1]
  • s prints the value [] because it is a slice of length 0. There are no values to show when the length is 0, so there is nothing between the brackets. It is length 0 because it was specified as such in the make call. When using make to make a slice, the second argument is the length of the slice.
  • s[0:10] may print [1 0 0 0 0 0 0 0 0 0] because it is allowed to re-slice an existing slice into its whole underlying capacity, not just the length. Since the re-slice goes from 0 to 10, it will include 10 values (the second bound of the slice is non-inclusive). That's why you see all 10 values in the printout.
  • As a bonus point, s[0:10] cannot be [] because that would mean you specify a slice of length 10 and get in return a slice of length 0. In Go, the length of a slice s[a:b] will always have a length of b - a. If that's not possible, then the program will panic. It will not give you a slice of some other length. See the explanation of these rules in the language specification: https://go.dev/ref/spec#Slice_expressions

huangapple
  • 本文由 发表于 2022年7月9日 19:25:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/72920962.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定