str := "1,2,3,4" //case 1
arr := strings.Split(str, ",")
fmt.Printf("%q\n", arr)
fmt.Println(len(arr))
str = "" //case 2
arr = strings.Split(str, ",")
fmt.Printf("%q\n", arr)
fmt.Println(len(arr))
// output
["1" "2" "3" "4"]
4
[""]
1
在case1的情况,没什么问题;在case2的情况下,len(arr) 的值是 1
原因:
Split(s,sep string) 方法底层调用下面的方法genSplit(),其中n=-1<0意思是把待查字符串中所有的分段都返回
func genSplit(s, sep string, sepSave, n int) []string {
if n == 0 {
return nil
}
if sep == "" {
return explode(s, n)
}
if n < 0 {
n = Count(s, sep) + 1
}
a := make([]string, n)
n--
i := 0
for i < n {
m := Index(s, sep)
if m < 0 {
break
}
a[i] = s[:m+sepSave]
s = s[m+len(sep):]
i++
}
a[i] = s
return a[:i+1]
}
n = Count(s, sep) + 1,其中的Count()方法如下,也是调用的底层的internal/bytealg包里的CountString(s string,sep byte) int方法
func Count(s, substr string) int {
// special case
if len(substr) == 0 {
return utf8.RuneCountInString(s) + 1
}
if len(substr) == 1 {
return bytealg.CountString(s, substr[0])
}
n := 0
for {
i := Index(s, substr)
if i == -1 {
return n
}
n++
s = s[i+len(substr):]
}
}
CountString()的方法如下:
func countGenericString(s string, c byte) int {
n := 0
for i := 0; i < len(s); i++ {
if s[i] == c {
n++
}
}
return n
}
为什么空字符串会返回长度为1的空字符串数组——[""],就是因为countGenericString("",",")返回了0,这个0在genSplit()里第9行与1相加,在第12行处创建了一个长度为1的字符串数组。
它这么做也不是因为啥,只是说我给你一个字符串a,按某个字符串b进行分割,如果没有能分割的,那就返回a,返回原始的数据。
Split()方法原理,遍历了两次字符串,第一轮的作用在于创建长度为n的slice,为第二轮来存放最后的结果。空间换时间。空间O(n),时间O(n)。