
字节笔记本
2026年10月7日 · 约 8 分钟读完
开头、结尾和下标分开查
strings 包里有前缀、后缀和子串位置,只是名字不叫 startswith。HasPrefix 看开头,HasSuffix 看结尾,Index 看第一次出现的下标,找不到返回 -1。同一段对话后半还有一个五次循环,它算的是另一件事,不要和这三个函数写在一个判断里。

Hello 在开头,World 在下标 7
样本字符串是 Hello, World!。strings.HasPrefix(s, "Hello") 为真。strings.HasSuffix(s, "!") 为真。strings.Index(s, "World") 得到 7。逗号和空格占了开头六个字符之后的位置,W 落在下标 7。下标从 0 起。用别的语言里“第 7 个字符”的习惯去对,会差一。
找不到时 Index 返回 -1,不是 0。0 是开头就匹配。把 -1 当成“在最前”会切错切片。判断之前先看是不是负的,再拿去当切片边界。
这三个函数都区分大小写。样本的 Hello 能匹配,是因为大小写一致。hello 不会让 HasPrefix 为真。需要忽略大小写时,先把两边收成同一种写法,再调用。标准库这三份函数本身不带忽略大小写的开关。
空前缀会让 HasPrefix 为真,空串是任何字符串的前缀。业务上若前缀来自输入,先拒绝空串,否则每条记录都像匹配成功。
后半段循环不是字符串函数
同一文件里接着有一段 main。x1 从 0 开始,x2 从 1 开始,循环变量从 0 到 4,共五次。每次把 x2 存进 xtemp,x2 变成 x2 + x1,再把 xtemp 赋回 x1。这是用两个变量往前滚一拍。打印的是循环结束后的 x2。
把五步摊开:开始是 0 和 1。第一次之后是 1 和 1。第二次是 1 和 2。第三次是 2 和 3。第四次是 3 和 5。第五次是 5 和 8。打印 8。对话后半把输出写成 5,并把数列停在 5。按这五次赋值,结束时的 x2 是 8,不是 5。这和 HasPrefix 无关。若把这段放进字符串工具的例子里,读者会以为 8 是某个下标。它是循环结束后的第二个变量。
循环上界写成小于 5,不是小于等于 5。多一次会再往前滚一拍,打印的就不是 8。临时变量必须先接住旧的 x2。若先改 x1,下一拍加到的就不是原来的后一项。
这段没有导入 fmt 就调用了打印。完整程序要带上格式化包。对话的片段只展示循环。字符串三函数的导入是 strings。两个片段的导入不同,不要合成一个文件时漏掉其中一个。

先看返回值的含义
开头用 HasPrefix,结尾用 HasSuffix,位置用 Index。样本里 World 的下标是 7,感叹号在结尾,Hello 在开头。找不到是 -1。空前缀会成功,输入要先挡掉。后面那个五次循环打印的是 8,它不是下标。两段代码分开测。
下标和切片
Index 返回 7 时,s[7:] 从 W 开始,是 World!。s[:7] 是 Hello, ,含逗号和空格。若有人把 7 当成“第 7 个字符”从 1 数,会切到逗号上。样本用 fmt.Println 打出 true true 7 这一类结果时,第三个是下标,不是长度。Hello, World! 的长度更长,不要用下标去对 len。
HasSuffix 为真只说明结尾是 !。它不说明前面是 World。要同时约束结尾和中间,两个函数都要调用。HasPrefix 为假时,不必再查 Index,开头已经不是预期。顺序可以是先前后缀,再位置。位置是 -1 时不要拿去切片,Go 的切片边界不允许负的下标。
大小写不一致时三个函数都失败。Hello 对 hello,HasPrefix 为假,Index 为 -1。业务需要忽略大小写,先转换再比较,转换要在副本上做,不要改掉原来要切的那份字符串,否则下标对的是转换后的内容,和原文切片错位。
空前缀、空后缀会使前后缀判断为真。来自参数的前后缀先看长度。长度为 0 就返回“未提供”,而不是“匹配成功”。Index 找空串的结果不要拿来当业务位置。样本找的是 World 和 !,都不是空。
五次循环那一段保持独立。x1、x2 从 0 和 1 走到 5 和 8,打印 8。它不调用 strings。测试文件分开,避免一个人改循环上界时把字符串样例的断言弄脏。循环若写成小于等于 5,会多滚一拍,打印不再是 8。临时变量必须先保存旧的 x2。
HasPrefix 看的是 Hello,为真。HasSuffix 看的是感叹号,为真。Index 找 World 得到 7,因为下标从 0 开始,逗号和空格占在 W 前面。用 7 做切片,s[7:] 从 W 起。把 7 当成从 1 数的第 7 个字符,会切到逗号上。
找不到时返回 -1。0 表示刚好在开头。负的下标不能拿去切片。空的前缀会让 HasPrefix 为真,参数要先看长度。这三个函数都区分大小写,样本能对上是因为大小写一致。忽略大小写要先在副本上转换,再比较,避免下标和原文错位。
循环从 x1 = 0、x2 = 1 出发,上界是小于 5。每一步先把 x2 放进 xtemp,再让 x2 变成两者之和,最后把 xtemp 写回 x1。五步之后打印 8。上界写成小于等于 5 会多一拍。先改 x1 会丢掉旧的后一项。片段里直接调用了打印,完整文件还要带上格式化包的导入。这段不调用 strings,不要和前缀测试写在同一个断言里。
字符串样本是 Hello, World!。开头匹配 Hello 为真,结尾匹配感叹号为真,World 的下标是 7。这三个结果来自三个函数,不能用其中一个代替另外两个。前缀为真并不说明 World 一定在下标 7,那要再调用 Index。后缀为真只说明最后一个字符是感叹号。把打印出的 7 拿去和 len 比较,长度并不等于 7。切片边界用下标,长度用 len,两者不要混。循环那段的 8 更不能拿来切片。8 是五次加法之后的 x2。若有人按对话后半的说法去断言输出为 5,测试会失败,因为代码走到的是 8。修正断言,不要为了迎合说明去把上界改成别的次数。
把样本读完再写断言。开头那一次比较为真,结尾那一次比较为真,子串位置是七。循环打印是八。四件事来自两段互不相干的代码。说明文字把循环结果说成五,那一句不要再抄进注释或测试。上界是小于五,临时变量要先接住旧值。完整文件还要补上打印所需的导入。字符串三函数的导入是另一个包。合成文件时两个导入都留下,测试仍然分开。再核对一遍赋值。开始两个数是零和一。五次之后第二个数是八。若少滚动一次,打印会停在五,那是说明文字里的结果,不是这段循环的结果。测试要跑这段循环本身,不要改上界去迁就说明。字符串例子只断言前缀、后缀和下标。两边的失败原因不同,混在一个测试里会看不出是哪一段被改过。位置七不能当成字符串长度。长度要单独取。负的位置不能拿去切。空参数会让前后缀判断成功,要先挡住。



