从零学习 Go 语言(04):byte、rune与字符串

hello_wbm · · 1140 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Hi,大家好呀,我是一个刚学习 Go 语言不久的新手,在入门 Golang 的这段时间里,我写了很多详细的学习笔记,很适合新手学习噢。这些文章已经发布在我的个人微信公众号里:《Go编程时光》里,今天开始将文章内容搬运到这里,希望有更多的人看到,给更的人带来帮助,但是这里文章会相对滞后,想获取最新文章,可以前往关注《Go编程时光》,请放心关注,这是一个纯分享的号,完全没有广告。 **系列导读 ** [从零学习 Go 语言(01):一文搞定开发环境的搭建](https://studygolang.com/articles/27365) [从零学习 Go 语言(02):学习五种变量创建的方法](https://studygolang.com/articles/27432) [从零学习 Go 语言(03):数据类型之整型与浮点型](https://studygolang.com/articles/27440) --- ## 1. byte 与 rune **byte**,占用1个节字,就 8 个比特位,所以它和 `uint8` 类型本质上没有区别,它表示的是 ACSII 表中的一个字符。 如下这段代码,分别定义了 byte 类型和 uint8 类型的变量 a 和 b ```go import "fmt" func main() { var a byte = 65 // 8进制写法: var c byte = '\101' 其中 \ 是固定前缀 // 16进制写法: var c byte = '\x41' 其中 \x 是固定前缀 var b uint8 = 66 fmt.Printf("a 的值: %c \nb 的值: %c", a, b) // 或者使用 string 函数 // fmt.Println("a 的值: ", string(a)," \nb 的值: ", string(b)) } ``` 在 ASCII 表中,由于字母 A 的ASCII 的编号为 65 ,字母 B 的ASCII 编号为 66,所以上面的代码也可以写成这样 ```go import "fmt" func main() { var a byte = 'A' var b uint8 = 'B' fmt.Printf("a 的值: %c \nb 的值: %c", a, b) } ``` 他们的输出结果都是一样的。 ``` a 的值: A b 的值: B ``` **rune**,占用4个字节,共32位比特位,所以它和 `uint32` 本质上也没有区别。它表示的是一个 Unicode字符(Unicode是一个可以表示世界范围内的绝大部分字符的编码规范)。 ```go import ( "fmt" "unsafe" ) func main() { var a byte = 'A' var b rune = 'B' fmt.Printf("a 占用 %d 个字节数\nb 占用 %d 个字节数", unsafe.Sizeof(a), unsafe.Sizeof(b)) } ``` 输出如下 ``` a 占用 1 个字节数 b 占用 4 个字节数 ``` 由于 byte 类型能表示的值是有限,只有 2^8=256 个。所以如果你想表示中文的话,你只能使用 rune 类型。 ```ro var name rune = '中' ``` 或许你已经发现,上面我们在定义字符时,不管是 byte 还是 rune ,我都是使用单引号,而没使用双引号。 对于从 Python 转过来的人,这里一定要注意了,在 Go 中单引号与 双引号并不是等价的。 单引号用来表示字符,在上面的例子里,如果你使用双引号,就意味着你要定义一个字符串,赋值时与前面声明的前面会不一致,这样在编译的时候就会出错。 ```go cannot use "A" (type string) as type byte in assignment ``` 上面我说了,byte 和 uint8 没有区别,rune 和 uint32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢? 理由很简单,因为uint8 和 uint32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。 ## 2. 字符串 字符串,可以说是大家很熟悉的数据类型之一。定义方法很简单 ```go var mystr string = "hello" ``` 上面说的byte 和 rune 都是字符类型,若多个字符放在一起,就组成了字符串,也就是这里要说的 string 类型。 比如 `hello` ,对照 ascii 编码表,每个字母对应的编号是:104,101,108,108,111 ```go import ( "fmt" ) func main() { var mystr01 sting = "hello" var mystr02 [5]byte = [5]byte{104, 101, 108, 108, 111} fmt.Printf("mystr01: %s\n", mystr01) fmt.Printf("mystr02: %s", mystr02) } ``` 输出如下,mystr01 和 mystr02 输出一样,说明了 string 的本质,其实是一个 byte数组 ``` mystr01: hello mystr02: hello ``` 通过以上学习,我们知道字符分为 byte 和 rune,占用的大小不同。 这里来考一下大家,`hello,中国` 占用几个字节? 要回答这个问题,你得知道 Go 语言的 string 是用 uft-8 进行编码的,英文字母占用一个字节,而中文字母占用 3个字节,所以 `hello,中国` 的长度为 5+1+(3*2)= 12个字节。 ```go import ( "fmt" ) func main() { var country string = "hello,中国" fmt.Println(len(country)) } // 输出 12 ``` 以上虽然我都用双引号表示 一个字符串,但这并不是字符串的唯一表示方式。 除了双引号之外 ,你还可以使用反引号。 大多情况下,二者并没有区别,但如果你的字符串中有转义字符`\` ,这里就要注意了,它们是有区别的。 使用反引号号包裹的字符串,相当于 Python 中的 raw 字符串,会忽略里面的转义。 比如我想表示 `\r\n` 这个 字符串,使用双引号是这样写的,这种叫解释型表示法 ```go var mystr01 string = "\\r\\n" ``` 而使用反引号,就方便多了,所见即所得,这种叫原生型表示法 ```go var mystr02 string = `\r\n` ``` 他们的打印结果 都是一样的 ```go import ( "fmt" ) func main() { var mystr01 string = "\\r\\n" var mystr02 string = `\r\n` fmt.Println(mystr01) fmt.Println(mystr02) } // output \r\n \r\n ``` 如果你仍然想使用解释型的字符串,但是各种转义实在太麻烦了。你可以使用 fmt 的 `%q` 来还原一下。 ```go import ( "fmt" ) func main() { var mystr01 string = `\r\n` fmt.Println(`\r\n`) fmt.Printf("的解释型字符串是: %q", mystr01) } ``` 输出如下 ```go \r\n 的解释型字符串是: "\\r\\n" ``` 同时反引号可以不写换行符(因为没法写)来表示一个多行的字符串。 ```go import ( "fmt" ) func main() { var mystr01 string = `你好呀! 我的公众号是: Go编程时光,欢迎大家关注` fmt.Println(mystr01) } ``` 输出如下 ``` 你好呀! 我的公众号是: Go编程时光,欢迎大家关注 ``` --- ![](http://image.python-online.cn/20200321153457.png)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1140 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传