好像没区别,对吧? 来看个全面的对比:
package main
import ( "fmt" "reflect" )
func main(){ asci:="abc" ch:="我是中国人" mix:="i am 中国人" fmt.Println( reflect.TypeOf(asci), reflect.TypeOf(ch), reflect.TypeOf(mix), ) fmt.Println( reflect.TypeOf(asci[0]), reflect.TypeOf(ch[0]), reflect.TypeOf(mix[0]), ) for i,v:=range asci{ fmt.Println(reflect.TypeOf(asci[i]), reflect.TypeOf(v), string(v), string(asci[i]), string(asci[:3]) ) break } for i,v:=range ch{ fmt.Println(reflect.TypeOf(asci[i]), reflect.TypeOf(v),string(v), string(ch[i]), string(ch[:3])) break } for i,v:=range mix{ fmt.Println(reflect.TypeOf(asci[i]), reflect.TypeOf(v), string(v), string(mix[i]), string(mix[:3])) break }
string string string uint8 uint8 uint8 uint8 int32 a a abc uint8 int32 我 æ 我 uint8 int32 i i i a
分析:
原来是 byte 表示一个字节,rune 表示四个字节,相当于4个byte,可以存放utf8字符。
由此,string[i]可能不是ascii,就显示成乱码。
s := "截取中文"
//试试这样能不能截取?
fmt.Println(s[:3])
明显是不能的。
正确做法:
fmt.Println(string([]rune(s)[:3]))
总结 :
1. for range 时会把 string[i]进行强制转换为 rune, 如果我们只需要byte,就多此一举了.
2. 默认按rune处理是非常稳妥的方式,不会有乱码。
3. string默认按[]byte进行解析,对含非ascii string的slice操作会产生乱码,需要转成rune.
|
请发表评论