美文网首页
4. Go 语言数据类型:byte、rune与字符串

4. Go 语言数据类型:byte、rune与字符串

作者: 王炳明 | 来源:发表于2020-04-26 12:38 被阅读0次

    Hi,大家好。

    我是明哥,在自己学习 Golang 的这段时间里,我写了详细的学习笔记放在我的个人微信公众号 《Go编程时光》,对于 Go 语言,我也算是个初学者,因此写的东西应该会比较适合刚接触的同学,如果你也是刚学习 Go 语言,不防关注一下,一起学习,一起成长。

    我的在线博客:http://golang.iswbm.com
    我的 Github:github.com/iswbm/GolangCodingTime


    1. byte 与 rune

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

    如下这段代码,分别定义了 byte 类型和 uint8 类型的变量 a 和 b

    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,所以上面的代码也可以写成这样

    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是一个可以表示世界范围内的绝大部分字符的编码规范)。

    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 类型。

    var name rune = '中'
    

    或许你已经发现,上面我们在定义字符时,不管是 byte 还是 rune ,我都是使用单引号,而没使用双引号。

    对于从 Python 转过来的人,这里一定要注意了,在 Go 中单引号与 双引号并不是等价的。

    单引号用来表示字符,在上面的例子里,如果你使用双引号,就意味着你要定义一个字符串,赋值时与前面声明的前面会不一致,这样在编译的时候就会出错。

    cannot use "A" (type string) as type byte in assignment
    

    上面我说了,byte 和 uint8 没有区别,rune 和 uint32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?

    理由很简单,因为uint8 和 uint32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。

    2. 字符串

    字符串,可以说是大家很熟悉的数据类型之一。定义方法很简单

    var mystr string = "hello"
    

    上面说的byte 和 rune 都是字符类型,若多个字符放在一起,就组成了字符串,也就是这里要说的 string 类型。

    比如 hello ,对照 ascii 编码表,每个字母对应的编号是:104,101,108,108,111

    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个字节。

    import (
        "fmt"
    )
    
    func main() {
        var country string = "hello,中国"
        fmt.Println(len(country))
    }
    // 输出
    12
    

    以上虽然我都用双引号表示 一个字符串,但这并不是字符串的唯一表示方式。

    除了双引号之外 ,你还可以使用反引号。

    大多情况下,二者并没有区别,但如果你的字符串中有转义字符\ ,这里就要注意了,它们是有区别的。

    使用反引号号包裹的字符串,相当于 Python 中的 raw 字符串,会忽略里面的转义。

    比如我想表示 \r\n 这个 字符串,使用双引号是这样写的,这种叫解释型表示法

    var mystr01 string = "\\r\\n"
    

    而使用反引号,就方便多了,所见即所得,这种叫原生型表示法

    var mystr02 string = `\r\n`
    

    他们的打印结果 都是一样的

    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 来还原一下。

    import (
        "fmt"
    )
    
    func main() {
        var mystr01 string = `\r\n`
        fmt.Println(`\r\n`)
        fmt.Printf("的解释型字符串是: %q", mystr01)
    }
    

    输出如下

    \r\n
    的解释型字符串是: "\\r\\n"
    

    同时反引号可以不写换行符(因为没法写)来表示一个多行的字符串。

    import (
        "fmt"
    )
    
    func main() {
        var mystr01 string = `你好呀!
    我的公众号是: Go编程时光,欢迎大家关注`
    
        fmt.Println(mystr01)
    }
    

    输出如下

    你好呀!
    我的公众号是: Go编程时光,欢迎大家关注
    

    系列导读

    01. 开发环境的搭建(Goland & VS Code)

    02. 学习五种变量创建的方法

    03. 详解数据类型:****整形与浮点型

    04. 详解数据类型:byte、rune与string

    05. 详解数据类型:数组与切片

    06. 详解数据类型:字典与布尔类型

    07. 详解数据类型:指针

    08. 面向对象编程:结构体与继承

    09. 一篇文章理解 Go 里的函数

    10. Go语言流程控制:if-else 条件语句

    11. Go语言流程控制:switch-case 选择语句

    12. Go语言流程控制:for 循环语句

    13. Go语言流程控制:goto 无条件跳转

    14. Go语言流程控制:defer 延迟调用

    15. 面向对象编程:接口与多态

    16. 关键字:make 和 new 的区别?

    17. 一篇文章理解 Go 里的语句块与作用域

    18. 学习 Go 协程:goroutine

    19. 学习 Go 协程:详解信道/通道

    20. 几个信道死锁经典错误案例详解

    21. 学习 Go 协程:WaitGroup

    22. 学习 Go 协程:互斥锁和读写锁

    23. Go 里的异常处理:panic 和 recover

    24. 超详细解读 Go Modules 前世今生及入门使用

    25. Go 语言中关于包导入必学的 8 个知识点

    26. 如何开源自己写的模块给别人用?

    27. 说说 Go 语言中的类型断言?

    28. 这五点带你理解Go语言的select用法


    相关文章

      网友评论

          本文标题:4. Go 语言数据类型:byte、rune与字符串

          本文链接:https://www.haomeiwen.com/subject/raudwhtx.html