Go string 详解
前言
字符串(string) 作为 go 语言的基本数据类型,在开发中必不可少,我们务必深入学习一下,做到一清二楚。
本文假设读者已经知道切片(slice)的使用,如不了解,可阅读 Go 切片 基本知识点
为了更好的理解后文,推荐先阅读 Unicode 字符集,UTF-8 编码
是什么
In Go, a string is in effect a read-only slice of bytes.
在 go 语言中,字符串实际上是一个只读的字节切片,其数据结构定义如下:
// runtime/string.go
type stringStruct struct {
str unsafe.Pointer // 指向底层字节数组的指针
len int // 字节数组的长度
}
注意:byte 其实是 uint8 的类型别名
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8
怎么用
func main() {
// 使用字符串字面量初始化
var a = "hi,狗"
fmt.Println(a)
// 可以使用下标访问,但不可修改
fmt.Printf("a[0] is %d\n", a[0])
fmt.Printf("a[0:2] is %s\n", a[0:2])
// a[0] = 'a' 编译报错,Cannot assign to a[0]
// 字符串拼接
var b = a + "狗"
fmt.Printf("b is %s\n", b)
// 使用内置 len() 函数获取其长度
fmt.Printf("a's length is: %d\n", len(a))
// 使用 for;len 遍历
for i := 0; i < len(a); i++ {
fmt.Println(i, a[i])
}
// 使用 for;range 遍历
for i, v := range a {
fmt.Println(i, v)
}
}
/* output
hi,狗
a[0] is 104
a[0:2] is hi
b is hi,狗狗
a's length is: 6
0 104
1 105
2 44
3 231
4 139
5 151
0 104
1 105
2 44
3 29399
*/
如果读者在看上面的代码时有疑惑,不用着急,下文将会挨个解读。
只读
字符串常量会在编译期分配到只读段,对应数据地址不可写入,相同的字符串常量不会重复存储
func main() {
var a = "hello"
fmt.Println(a, &a, (*reflect.StringHeader)(unsafe.Pointer(&a)))
a = "world"
fmt.Println(a, &a, (*reflect.StringHeader)(unsafe.Pointer(&a)))
var b = "hello"
fmt.Println(b, &b, (*reflect.StringHeader)(unsafe.Pointer(&b)))
}
/* output
字符串字面量 该变量的内存地址 底层字节切片
hello 0xc0000381f0 &{5033779 5}
world 0xc0000381f0 &{5033844 5}
hello 0xc000038220 &{5033779 5}
*/
可以看到 hello 在底层只存储了一份
for;len 遍历
go 的源代码都是 UTF-8 编码格式的,上例中的”狗“字占用三个字节,即 231 139 151(Unicode Character Table),所以上例的运行结果很清楚。
于此同时,也可以将字符串转化为字节切片
func main() {
var a = "hi,狗"
b := []byte(a)
fmt.Println(b) // [104 105 44 231 139 151]
}
for;range 遍历
The Unicode standard uses the term "code point" to refer to the item represented by a single value.
在 Unicode 标准中,使用术语 code point
来表示由单个值表示的项,通俗点来说,U+72D7(十进制表示为 29399)代表符号 ”狗“
"Code point" is a bit of a mouthful, so Go introduces a shorter term for the concept: rune.
code point 有点拗口,所以在 go 语言中专门有一个术语来代表它,即 rune
注意:rune 其实是 int32 的类型别名
// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32
在对字符串类型进行 for;range 遍历时,其实是按照 rune 类型来解码的,所以上例的运行结果也很清晰。
与此同时,也可以将字符串转化为 rune 切片
func main() {
// 使用字符串字面量初始化
var a = "hi,狗"
r := []rune(a)
fmt.Println(r) // [104 105 44 29399]
}
当然我们也可以使用 "unicode/utf8"
标准库,手动实现 for;range 语法糖相同的效果
func main() {
var a = "hi,狗"
for i, w := 0, 0; i < len(a); i += w {
runeValue, width := utf8.DecodeRuneInString(a[i:])
fmt.Printf("%#U starts at byte position %d\n", runeValue, i)
w = width
}
}
/* output
U+0068 'h' starts at byte position 0
U+0069 'i' starts at byte position 1
U+002C ',' starts at byte position 2
U+72D7 '狗' starts at byte position 3
*/
参考
Strings, bytes, runes and characters in Go
Go string 详解的更多相关文章
- Java的String详解
Java的String详解 博客分类: Java javaStringString详解常用方法 Java的String类在开发时经常都会被使用到,由此可见String的重要性.经过这次认真仔细的学习 ...
- Python操作redis字符串(String)详解 (三)
# -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1.SET 命令用于设置 ...
- [读书笔记]C#学习笔记八:StringBuilder与String详解及参数传递问题剖析
前言 上次在公司开会时有同事分享windebug的知识, 拿的是string字符串Concat拼接 然后用while(true){}死循环的Demo来讲解.其中有提及string操作大量字符串效率低下 ...
- String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)
本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...
- Java堆、栈和常量池以及相关String详解
一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...
- String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别
本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...
- String 详解
String String对象不可变,当对象创建完毕之后,如果内容改变则会创建一个新的String对象,返回到原地址中. 不可变优点: 多线程安全. 节省空间,提高效率. 源码: public fin ...
- java String 详解
1.java语言的字符串序列是通过字符串类实现的.java提供了3个字符串类:String类.StringBuilder类和StringBuffer类.String类是不变字符串,StringBuff ...
- String详解
在开发中,我们都会频繁的使用String类,掌握String的实现和常用方法是必不可少的,当然,我们还需要了解它的内部实现. 一. String的实现 在Java中,采用了一个char数组实现Stri ...
- C#String详解
字符串:stringLength - 字符串的长度. TrimStart() 压缩空格即消除字符串开始空格TrimEnd() 消除结尾空格Trim() 同时消除开头和结尾空格.注:中间空格不消除,因为 ...
随机推荐
- 09- monkey命令详解
安装模拟器 如果你没有手机可以安装个模拟器,如果有手机了,忽略此步骤. 1.下载模拟器:http://www.xyaz.cn/ 2.安装:直接默认安装. 3.打开安卓模拟器,设置-关于手机-点击版本号 ...
- 【Redis连接超时】记录线上RedisConnectionFailureException异常排查过程
项目架构: 部分组件如下: SpringCloudAlibaba(Nacos+Gateway+OpenFeign)+SpringBoot2.x+Redis 问题背景: 最近由于用户量增大,在高峰时期, ...
- Sass中连体符(&)的运用
在CSS中,这种想法是无法实现的,但在Sass中,可以轻松的通过连体符&来实现.这也是我们今天要说的. 我们先来回忆一下,CSS中常见的一组样式: /*页面中链接的颜色*/ a {clolor ...
- windows-API劫持(API-HOOK)
API Hook ApiHook又叫做API劫持,也就是如果A程序调用了B.cll里面的C函数,我们可以做到当A调用C函数执行的时候,直接执行我们自己事先准备好的函数,之后我们在执行真正的C,当然我们 ...
- node-util
Node.js 常用工具 util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足. util.inherits util.inherit ...
- [CTF]维吉尼亚密码(维基利亚密码)
[CTF]维吉尼亚密码(维基利亚密码) ----------------------百度百科 https://baike.baidu.com/item/维吉尼亚密码/4905472?fr=aladdi ...
- Qt链接MySQL发布后Drive not loadedDrive not loaded怎么办
缺少动态链接库!把MySQL文件夹下面带dll.lib的全复制进去就行了
- 【Web前端HTML5&CSS3】03-字符实体与语义标签
笔记来源:尚硅谷Web前端HTML5&CSS3初学者零基础入门全套完整版 目录 字符实体与语义标签 1. 字符实体 2. meta标签 3. 语义标签 4. 块元素与行内元素 块元素(bloc ...
- .NET平台系列目录
本系列主要讲解微软.NET平台发展历程以及.NET框架技术.包含.NET Framework..NET Core.Xamarin..NET Standrad等技术与应用. 1..NET平台系列 .NE ...
- IP子网划分与聚合
一:IP地址: IP地址是由32位2进制数组成,每8位一组.由点分十进制表达. IP地址可以分为五类 A类(1.0.0.0-126.255.255.255),127.0.0.1 为本地回环地址. B类 ...