Go--谈谈byte和rune

136 阅读2分钟
先聊两句

在我的印象中,一直认为byterune是差不多的,都是表示字符类型。但是在做题的时候让我意识到了错误认知。

题目很简单就是将字符串中的?替换成不重复的字母,但是在写的过程中却报了错

for i, v := range s {
   if v == '?' {
      for k := 'a'; k <= 'z'; k++ {
         if k != s[i+1] { //error:无效运算: k != s[i+1](类型 int32 和 uint8 不匹配)
            s = s[:i] + string(k) + s[i+1:]
         }
      }
   }
}

这让我产生疑惑,'a's[i]不是一个类型吗?

s := "zsfh?sab?a"
fmt.Printf("%T\n", 'a')     
fmt.Printf("%T\n", s[0])

//int32
//uint8

测试结果确实如此,字符'a'是int32类型,而字符串中的某一字符s[i]是uint8类型

正文开始

在go语言中,我们通常所说的字符,其实是rune类型,与可以说是int32类型,它占用4个字节的位置,也就是32比特位,他表示的是一个Unicode字符,另外,由于golang使用的是utf8编码,一个中文占3个字节,因此只能用rune表示中文

byte类型,占用1个字节,8个比特位,所以他本质上和uint8没有区别,他表示的是ACSII表中的一个字符

那字符串中的字符到底是什么类型呢?我们通过for循环测试一下

s := "zsfh?sab?a"

for i := range s {
   fmt.Printf("%T\t", s[i])
}
//uint8   uint8   uint8   uint8   uint8   uint8   uint8   uint8   uint8   uint8
for _, v := range s {
   fmt.Printf("%T\t", v)
}
//int32   int32   int32   int32   int32   int32   int32   int32   int32   int32

for i := 0; i < len(s); i++ {
   fmt.Printf("%T\t", s[i])
}
//uint8   uint8   uint8   uint8   uint8   uint8   uint8   uint8   uint8   uint8

根据for循环的结果我们可以得出,当我们根据索引位置来获取数据时,我们得到的是uint8类型的字符,当我们通过for range直接获取数据时,我们得到是int32类型的数据