go字符串转byte_Go字符串初探

b730852ed53c8fe52244fbf89a88da98.png

这篇博文的知识,主要是阅读了Go的官方博客在2013年发表的一篇,名为《Strings, bytes, runes and characters in Go》的文章,里面解释了Go语言中的stringbyte以及rune类型以及Go中的编码方式等内容。

自己才刚刚接触Go,内容必定有所疏漏,欢迎评论指正。

相关概念的辨析

  1. 字符串、字符、字节、位
  2. bitbit是计算机中最小的存储单位,一个bit表示一个二进制位,存储01
  3. 字节byte:一个byte由8个bit组成。在Go中,byte也是一种类型,其底层实际上是一种uint8类型的别名,主要是为了区分字节类型和uint8类型,可以指代一个ASCII的字符。
  4. 字符:字符表示一个可以正常显示的一个符号,譬如一个字符串abc,其中abc都是字符,在Go中,一个字符对应一个rune类型值。
  5. 字符串stringGo中的字符串,实际上是只读的字节切片。
  6. Unicode码点:实际上,字符的概念非常难以定义,在Unicode标准中,使用码点来代指,一个Unicode表示的个体。其表示是码点,其值是一串数字。
  7. rune类型:其是Go中,用以表示一个字符的类型,是int32类型的别名,为了区别表示字符类型以及int32类型。

字符串是字节的切片

我们都知道,在Go当中,字符串是字节的切片。跟JavaScipt有非常大的不同,主要体现在下面这个例子当中:

func test() {
  s := "Hello,世界"
  fmt.Println(len(s))
}

这个函数的输出是12,按照直觉来讲,输出应该是8才对。但是,正因为字符串是字节的切片,故取字符串Hello,世界,实际上是在取其对应的字节切片的长度。而在Go中是采用utf-8编码,一个汉字对应着3个字节,因此才得到了12这个数字。

为了验证这个说法,我们取其对应字节的输出:

func test() {
  s := "Hello,世界"
  for i := 0; i < len(s); i++ {
    fmt.Printf("% x", s[i])
  }
}

输出为,12个字节:

48 65 6c 6c 6f 2c e4 b8 96 e7 95 8c

Unicodeutf-8

我们知道,Go中,都是采用utf-8来对Unicode进行编码的,这种编码方式有着动态大小的特点,借用Go语言圣经中的一张图来解释:

fc49e8b29f8e52aacf0b67766d49ca80.png

表示不同范围Unicode值,编码采用了不同个数的字节,我们常用的汉字,就一般是使用3个字节去表示的。

26ca7662b380b3b22ec1a8b2b114418f.png
从utf-8格式转变为unicode编码

上面这个例子展示了字符,是如何编码和解码的。其用Unicode表示,为2个字节,编码为utf-8则为3个字节。

rune类型

如果我们始终用若干字节去表示一个字符,那未免也太过繁琐。同时,我们上面知道取一个字符串长度,取得的是这个字符串对应字节的长度,那么我们用传统的for循环,取去的字符串中的每个字符,其结果是绝对不符合我们的期望的。

Go就专门为字符定义了字符类型rune。它是int32类型的别名,主要就是用来处理Unicode字符的。之所以,其对应的是int32类型,这主要是因为utf-8编码,最大会产生4个字节的大小的值,故对应了int32类型。

Go中想要按照正常的方式,遍历一个字符串,可以采用使用for range的形式,来对一字符串遍历:

func test() {
  s := "Hello,世界"
  for _, val := range s {
    fmt.Printf("%#Un", val)
  }
}

使用for range循环,实际上就是在字符串中对字符rune进行遍历。输出为:

U+0048 'H'
U+0065 'e'
U+006C 'l'
U+006C 'l'
U+006F 'o'
U+002C ','
U+4E16 '世'
U+754C '界'

其次,也可以使用标准库对字符串进行处理,如使用unicode/utf8库中的DecodeRuneInString方法,输入一个字节切片,返回一个rune值和其使用utf-8编码的字节宽度。

为什么要编码

实际上,现在Unicode已经收录了,超过12万个字符,我们如果直接使用一个int32的序列来存储所有的字符就已经足够使用,为什么还要采用utf-8这种编码模式?

主要是因为,如果统一使用固定长度bit来存储所有的字符,会导致存储空间的极大浪费。我们在日常的使用中,大部分时候,都是使用到了ASCII可以表示的一些字符,只有少数情况下,使用的字符会超出ASCII的表示范围。因此,我们需要使用utf-8这种变长的编码工具,来为我们节约空间。

参考

  1. Strings,bytes,runes and characters in Go
  2. Go语言程序设计
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值