type
Post
status
Published
date
May 19, 2022
slug
go-bottom-up-book-note-5
summary
Go语言底层原理剖析 第五章 读书笔记
tags
go
note
category
学习笔记
icon
password
书名: Go语言底层原理剖析 基于 Go 1.14 其他链接: 豆瓣链接, 示例源码及勘误

字符串

字符串本质

go的字符串string无法修改的, 其底层为rune数组
type StringHeader struct { // 16 字节 Data uintptr //指向底层的字符数组 Len int //字符串的长度 }
go中所有文件都采用UTF-8的编码方式, 字符常量也使用UTF-8的字符编码集 由于UTF-8的长度可变性, 字符串的长度未必是直观感觉上的长度, 而是指字节长度

符文类型

rune类型, 其实是int32的别称 当使用range遍历字符串, 访问的将不是单字节, 而是解释过的rune

字符串工具函数

主要在stringsstrconv包中

字符串底层原理

字符串解析

作为一个常量, 字符串常量的标识是单号和双引号
var s1 string = `test` var s2 string = "test"
两者的解析方式有所区别, 单撇号的解析只需成对即可 而双引号中, 不能出现换行符, 会对字符串中的\进行转义

编译时字符串拼接

字符串的拼接使用操作符 +
当操作符两边均为字符串常量时, gc在语法解析阶段会调用noder.sum函数来拼接这些常量, 也就是说, 字符串常量间的拼接可以在编译时完成
具体操作为: 将所有的字符串常量都放入字符串数组中, 再调用strings.Join来拼接

运行时字符串拼接

当涉及字符串变量的拼接时, 则拼接操作无法在编译时完成, 必须推迟到运行时才能解决
变量间的拼接, 本质上是寻找一个更大的空间, 通过内存复制的方式将拼接后的字符串放进去
需要注意的是, 拼接时会检查拼接后的字符串的长度, 长度小于32字节时, 会有一个临时的缓存供其使用(不涉及内存的复制?), 而大于32字节时, 则需要到堆区申请空间, 期间涉及内存复制(慢)

字符串与字节数组的转换

使用时是显示强制类型转换, 实现原理仍是复制
字节数组to字符串: 调用slicebytetostring函数 字符串to字节数组: 调用stringtoslicebyte函数
与字符串变量的拼接类似, 二者均以32字节为界, 将决定是否需要申请堆内存

总结

核心在于: 字符串本身是不可修改的, 各种操作均需要考虑性能损耗 以及区分字符串字节数组这两个概念
Ubuntu搭建RSSHub记录《废土谣》留档