Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24139 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

36 | unicode与字符编码

郝林 2018-11-02
到目前为止,我们已经一起陆陆续续地学完了 Go 语言中那些最重要也最有特色的概念、语法和编程方式。我对于它们非常喜爱,简直可以用如数家珍来形容了。
在开始今天的内容之前,我先来做一个简单的总结。

Go 语言经典知识总结

基于混合线程的并发编程模型自然不必多说。
数据类型方面有:
基于底层数组的切片;
用来传递数据的通道;
作为一等类型的函数;
可实现面向对象的结构体;
能无侵入实现的接口等。
语法方面有:
异步编程神器go语句;
函数的最后关卡defer语句;
可做类型判断的switch语句;
多通道操作利器select语句;
非常有特色的异常处理函数panicrecover
除了这些,我们还一起讨论了测试 Go 程序的主要方式。这涉及了 Go 语言自带的程序测试套件,相关的概念和工具包括:
独立的测试源码文件;
三种功用不同的测试函数;
专用的testing代码包;
功能强大的go test命令。
另外,就在前不久,我还为你深入讲解了 Go 语言提供的那些同步工具。它们也是 Go 语言并发编程工具箱中不可或缺的一部分。这包括了:
经典的互斥锁;
读写锁;
条件变量;
原子操作。
以及 Go 语言特有的一些数据类型,即:
单次执行小助手sync.Once
临时对象池sync.Pool
帮助我们实现多 goroutine 协作流程的sync.WaitGroupcontext.Context
一种高效的并发安全字典sync.Map
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(19)

  • wade
    而后三个十六进制数7231、597d和8005都相对较大,它们分别表示中文字符'爱'、'好'和'者'。这些中文字符对应的 UTF-8 编码值,都需要使用三个字节来表达。所以,这三个数就是把对应的三个字节来表达。所以,这三个数就是把对应的三个字节的编码值,转换为整数后得到的结果。

    "爱好者"对应的7231、597d、8005,不是UTF-8编码值,是unicode码点。unicode码点和最终计算器存储用的utf-8编码值不是一样的。转换成rune的时候rune切片每个元素存储一个unicode码点,也就是string里的一个字符转成rune切片的一个元素。string是以utf-8编码存储,byte切片也就是存储用的string用utf-8编码存储后的字节序。

    unicode和utf-8的关系,可以看这个文章
    http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
    2018-11-07
    15
  • 冰激凌的眼泪
    src文件编码是utf8
    string是utf8编码的mb,len(string)是字节的长度
    string可以转化为[]rune,unicode码,32bit的数字,当字符看,len([]rune)为字符长度
    string可以转化为[]byte,utf8编码字节串,len([]byte)和len(string)是一样的
    for range的时候,迭代出首字节下标和rune,首字符下标可能跳跃(视上一个字符编码长度定)
    2018-11-05
    9
  • 冰激凌的眼泪
    看rune大小
    转成byte看长度
    加个小尾巴,range看间隔
    2018-11-02
    3
  • 韡WEI
    rune怎么翻译?有道查的:神秘的记号。为什么这么命名这个类型?有没有什么故事?
    2018-11-15
    1
    2
  • Gryllus
    终于追上了进度

    作者回复: 🐂

    2018-11-02
    2
  • 安排
    一个unicode字符在内存中存的是码点的值还是utf8对应的编码值?

    作者回复: 内存里存的是 UTF-8 的编码值,会由 1~4 个字节组成。Unicode 代码点是 Unicode 标准中用来唯一标识字符的东西。

    2019-09-18
    1
    1
  • qiushye
    str := "Go 爱好者 "fmt.Printf("Th...

    您在文章里举的这个例子在Go后面多加了空格,会让人误解成遍历字符串可以跳过空格,github代码里没问题。

    作者回复: 收到,谢谢。已经通知编辑修正了。

    2019-09-05
    1
    1
  • 🤔
    + isrunesingle.go

    ```go
    package show_rune_length

    func isSingleCharA(c rune) bool {
    return int32(c) < 128
    }

    func isSingleCharB(c rune) bool {
    data := []byte(string(c))
    return len(data) == 1
    }

    func isSingleCharC(c rune) bool {
    data := string(c) + " "

    for i, _ := range data {
    if i == 0 {
    continue
    }

    if i == 1 {
    return true
    } else {
    return false
    }
    }

    return false
    }
    ```

    + isrunesingle_test.go

    ```go
    package show_rune_length

    import (
    "testing"

    "github.com/stretchr/testify/assert"
    )

    type CharJudger func(c rune) bool

    func TestIsSingleChar(t *testing.T) {

    for _, judger := range []CharJudger{
    isSingleCharA,
    isSingleCharB,
    isSingleCharC,
    } {
    assert.True(t, judger('A'))
    assert.True(t, judger(rune(' ')))
    assert.False(t, judger('😔'))
    assert.False(t, judger('爱'))
    }
    }
    ```

    作者回复: 可以用 unicode/utf8 代码包中的 RuneCount 函数。

    2019-04-22
    1
  • Andylee
    这篇文章把unicode和utf8区分的不是很清楚,正如上面有个网友说的rune切变16进制输出是字符的unicode的码点,而byte切片输出的才是utf8的编码

    作者回复: 这么说没错,不过rune在底层也是字节串。

    2018-12-16
    1
    1
  • 虢国技匠
    二刷
    2019-12-08
  • golangcode.top
    十六进制四个数字不是一共占用32位吗,一个字节不是8位嘛,这样不是占用4个字节吗?求大神解答

    作者回复: 你想问什么?十六进制的一位相当于二进制的四位。

    2019-10-10
  • 一个unicode字符点都是由两个字节存储,为什么在go语言中 type rune = int32 四个字节 而不是 type rune=16 两个字节啊

    作者回复: Unicode 代码点是一个抽象的概念,并且没有规定占用的字节数,只是说以“U+XXXX”的形式来表示。“X”还可能有 5 个或 6 个。

    Unicode 代码点是 Unicode 编码标准的一部分。但你要分清楚编码标准和编码格式(像 UTF-8、UTF-16 等等)的区别。前者是概念和表示法,后者是真正的落地格式。编码格式才是真正与存储占用(比如一个字符占用多少个字节)有关的东西。

    rune 类型的宽度是 4 个字节,那是因为 Go 语言使用 UTF-8 编码格式。这种格式编出来的码最多占用 4 个字节。

    2019-07-30
  • 张岳文
    我认为string的底层是Unicode, 而非UTF-8。只是string转成[]byte时,string转成了utf-8的序列。。。内存中的应该统一用unicode处理,而UTF-8是为了存储和传输才进行字节转换的。

    作者回复: 内存上的也是二进制储存的啊,Unicode 只是一个字符编码标准,不是编码格式。

    2019-07-23
  • benying
    打卡,讲的挺清楚的,谢谢
    2019-06-13
  • jacke
    string 底层是[]byte数组,我的疑问是:例子里面看出来,string转化为tune的时候,tune里面保存的是utf-8的代码点数据,string转化为[]byte的时候保存的是utf-8代码点对应的字节序。
    上面这些转化逻辑在哪里实现的?fmt.print里面?看了fmt.print找不到,string转为[]byte的实现函数stringtoslicebyte也没看到这部分逻辑

    作者回复: 你要知道,string 类型的值本身就是由 UTF-8 编码的一个个字节组成的,同时也可以看做是由一个个 Unicode 字符组成的。这不是在转换的时候才去做的。

    你既然已经找到了 stringtoslicebyte 函数,那就应该再去看看那个源码文件中的其他代码。可以从 rawstring 函数看起。等都看完了你就应该明白了。

    2019-05-12
  • Geek_1ed70f
    您是说 一个汉字的rune值 在计算机底层会被转成utf-8编码来 给计算机读取是吗?

    比如 一个"严"字 unicode为20005(十进制), utf-8编码是11100100 10111000 10100101(二进制),十进制就是14989477 , 我们平时打印只能看到 20005 它是什么时候转成14989477的啊

    作者回复: 存储的时候会以二进制的形式。另外如果你要看Unicode代码点。你这么转换比较混乱。你可以参看fmt包的文档,看看怎样才能把对应的进制值打印出来。

    2019-03-14
  • melody_future
    有点小晕,想请问下 rune 类型在内存的表现形式是 unicde 编码值,还是utf-8 编码值,你所说的底层指的是?

    作者回复: rune的底层表达使用的是Unicode代码点。
    但是,底层的存储用UTF-8编码。

    表达和存储这两者的关系你能分清楚吧?

    2019-03-06
  • 虢国技匠
    打卡:
    1、len函数对于字符串,得到的是字节长度
    2、utf-8 我以前看到的资料是 1-6个字节的可变长编码,go如果用rune,对于超过4个字节的utf-8字符怎么处理?

    作者回复: 目前utf-8是1~4个字节的。

    2019-01-27
  • ryon
    这章讲得还可以
    2018-11-05
收起评论
19
返回
顶部