go 中string[0]到底是rune还是byte?

时间:2022-07-23
本文章向大家介绍go 中string[0]到底是rune还是byte?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

好像没区别,对吧? 来看个全面的对比:

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.