Go的子字符串操作,不会出现索引超出范围的情况。

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

Go substring operation, no index out of range?

问题

我想知道为什么第二个 fmt.Println 中的 "s[1:]" 没有引发索引超出范围的错误?索引 1 显然超出了范围。

package main

import "fmt"

func main() {
   s := "J"
   //fmt.Println(s[1]) // 这会导致运行时错误:索引超出范围
   fmt.Println(s[1:]) // 为什么这个可以工作?索引值 1 显然超出了范围,但该语句打印一个空字符串
}

在 Go 语言中,字符串是由字节组成的不可变序列。当你使用索引访问字符串时,它会返回对应位置的字节值。在第一个 fmt.Println 语句中,你尝试访问索引 1,但由于字符串只有一个字节,所以索引超出了范围,导致运行时错误。

然而,在第二个 fmt.Println 语句中,你使用了切片操作符 "s[1:]"。切片操作符允许你从字符串中提取子字符串。当你使用 "s[1:]" 时,它会返回从索引 1 开始到字符串末尾的子字符串。如果起始索引超出了字符串的长度,它会返回一个空字符串,而不会引发索引超出范围的错误。因此,这个语句打印的结果是一个空字符串。

英文:

I would like know why "s[1:]" in the 2nd fmt.Println isn't throwing an index out of range error? Index 1 is clearly out of range

package main

import "fmt"

func main() {

   s := "J"

   //fmt.Println(s[1]) // This results in a runtime error: index out of range

   fmt.Println(s[1:]) // Why does this work? Index value 1 is clearly out of range, but the statement prints an empty string

}

答案1

得分: 11

根据语言规范所述,给定一个切片表达式

a[low : high]

对于数组或字符串,如果 0 <= low <= high <= len(a),则索引在范围内,否则索引就超出范围。 [...] 如果索引在运行时超出范围,将会发生运行时恐慌。

在你的例子中

s[1:]

low1highlen(s),而 len(s)1。由于 low <= len(s),所以不会发生恐慌。

英文:

As the language specification states, given a slice expression

a[low : high]

> For arrays or strings, the indices are in range if 0 &lt;= low &lt;= high &lt;= len(a), otherwise they are out of range. [...] If the indices are out of range at run time, a run-time panic occurs.

In your example

s[1:]

the low is 1, high is len(s) and len(s) is 1. Since low &lt;= len(s), there's no panic.

答案2

得分: 2

根据定义,它不会超出范围:在s上,从0到len(s)的任何位置都可以是范围的起始或结束。切片端点的工作方式设计得可以在不进行额外检查或计算的情况下编写正确的代码。特别是,

first  = s[:x]
second = s[x:]

s分成两部分,firstx个字节,second有剩余的字符串,对于0到len(s)之间的任何值。如果x == 0first将是一个空字符串,如果x == len(s)second将是一个空字符串。只有当允许从0到len(s)的完整范围时,才能满足这个条件,否则至少一个可能的分割位置将无法表示。

英文:

It is, by definition, not out of range: any position from 0 to len(s) can be the beginning or the end of a range on s. The way that slice endpoints work is designed so that you can write correct code without a lot of extra checks or arithmetic. In particular,

first  = s[:x]
second = s[x:]

will split s into two parts, with first having x bytes and second having the remainder of the string, for any value of x between 0 and len(s). first will be an empty string if x == 0, and second will be an empty string if x == len(s). This can only be true if the full range of values from 0 to len(s) is allowed, otherwise at least one of the possible split positions wouldn't be expressible.

huangapple
  • 本文由 发表于 2016年4月6日 08:05:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/36439191.html
匿名

发表评论

匿名网友

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

确定