前言

字符串(string) 作为 go 语言的基本数据类型,在开发中必不可少,我们务必深入学习一下,做到一清二楚。

本文假设读者已经知道切片(slice)的使用,如不了解,可阅读 Go 切片 基本知识点

为了更好的理解后文,推荐先阅读 Unicode 字符集,UTF-8 编码

是什么

In Go, a string is in effect a read-only slice of bytes.

在 go 语言中,字符串实际上是一个只读字节切片,其数据结构定义如下:

  1. // runtime/string.go
  2. type stringStruct struct {
  3. str unsafe.Pointer // 指向底层字节数组的指针
  4. len int // 字节数组的长度
  5. }

注意:byte 其实是 uint8 的类型别名

  1. // byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
  2. // used, by convention, to distinguish byte values from 8-bit unsigned
  3. // integer values.
  4. type byte = uint8

怎么用

  1. func main() {
  2. // 使用字符串字面量初始化
  3. var a = "hi,狗"
  4. fmt.Println(a)
  5. // 可以使用下标访问,但不可修改
  6. fmt.Printf("a[0] is %d\n", a[0])
  7. fmt.Printf("a[0:2] is %s\n", a[0:2])
  8. // a[0] = 'a' 编译报错,Cannot assign to a[0]
  9. // 字符串拼接
  10. var b = a + "狗"
  11. fmt.Printf("b is %s\n", b)
  12. // 使用内置 len() 函数获取其长度
  13. fmt.Printf("a's length is: %d\n", len(a))
  14. // 使用 for;len 遍历
  15. for i := 0; i < len(a); i++ {
  16. fmt.Println(i, a[i])
  17. }
  18. // 使用 for;range 遍历
  19. for i, v := range a {
  20. fmt.Println(i, v)
  21. }
  22. }
  23. /* output
  24. hi,狗
  25. a[0] is 104
  26. a[0:2] is hi
  27. b is hi,狗狗
  28. a's length is: 6
  29. 0 104
  30. 1 105
  31. 2 44
  32. 3 231
  33. 4 139
  34. 5 151
  35. 0 104
  36. 1 105
  37. 2 44
  38. 3 29399
  39. */

如果读者在看上面的代码时有疑惑,不用着急,下文将会挨个解读。

只读

字符串常量会在编译期分配到只读段,对应数据地址不可写入,相同的字符串常量不会重复存储

  1. func main() {
  2. var a = "hello"
  3. fmt.Println(a, &a, (*reflect.StringHeader)(unsafe.Pointer(&a)))
  4. a = "world"
  5. fmt.Println(a, &a, (*reflect.StringHeader)(unsafe.Pointer(&a)))
  6. var b = "hello"
  7. fmt.Println(b, &b, (*reflect.StringHeader)(unsafe.Pointer(&b)))
  8. }
  9. /* output
  10. 字符串字面量 该变量的内存地址 底层字节切片
  11. hello 0xc0000381f0 &{5033779 5}
  12. world 0xc0000381f0 &{5033844 5}
  13. hello 0xc000038220 &{5033779 5}
  14. */

可以看到 hello 在底层只存储了一份

for;len 遍历

go 的源代码都是 UTF-8 编码格式的,上例中的”狗“字占用三个字节,即 231 139 151(Unicode Character Table),所以上例的运行结果很清楚。

于此同时,也可以将字符串转化为字节切片

  1. func main() {
  2. var a = "hi,狗"
  3. b := []byte(a)
  4. fmt.Println(b) // [104 105 44 231 139 151]
  5. }

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 的类型别名

  1. // rune is an alias for int32 and is equivalent to int32 in all ways. It is
  2. // used, by convention, to distinguish character values from integer values.
  3. type rune = int32

在对字符串类型进行 for;range 遍历时,其实是按照 rune 类型来解码的,所以上例的运行结果也很清晰。

与此同时,也可以将字符串转化为 rune 切片

  1. func main() {
  2. // 使用字符串字面量初始化
  3. var a = "hi,狗"
  4. r := []rune(a)
  5. fmt.Println(r) // [104 105 44 29399]
  6. }

当然我们也可以使用 "unicode/utf8" 标准库,手动实现 for;range 语法糖相同的效果

  1. func main() {
  2. var a = "hi,狗"
  3. for i, w := 0, 0; i < len(a); i += w {
  4. runeValue, width := utf8.DecodeRuneInString(a[i:])
  5. fmt.Printf("%#U starts at byte position %d\n", runeValue, i)
  6. w = width
  7. }
  8. }
  9. /* output
  10. U+0068 'h' starts at byte position 0
  11. U+0069 'i' starts at byte position 1
  12. U+002C ',' starts at byte position 2
  13. U+72D7 '狗' starts at byte position 3
  14. */

参考

Strings, bytes, runes and characters in Go

为什么说go语言中的string是不可变的?

字符咋存?utf8咋编码?string啥结构?

Go string 详解的更多相关文章

  1. Java的String详解

    Java的String详解 博客分类: Java javaStringString详解常用方法  Java的String类在开发时经常都会被使用到,由此可见String的重要性.经过这次认真仔细的学习 ...

  2. Python操作redis字符串(String)详解 (三)

    # -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1.SET 命令用于设置 ...

  3. [读书笔记]C#学习笔记八:StringBuilder与String详解及参数传递问题剖析

    前言 上次在公司开会时有同事分享windebug的知识, 拿的是string字符串Concat拼接 然后用while(true){}死循环的Demo来讲解.其中有提及string操作大量字符串效率低下 ...

  4. String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)

    本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...

  5. Java堆、栈和常量池以及相关String详解

    一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...

  6. String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别

    本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...

  7. String 详解

    String String对象不可变,当对象创建完毕之后,如果内容改变则会创建一个新的String对象,返回到原地址中. 不可变优点: 多线程安全. 节省空间,提高效率. 源码: public fin ...

  8. java String 详解

    1.java语言的字符串序列是通过字符串类实现的.java提供了3个字符串类:String类.StringBuilder类和StringBuffer类.String类是不变字符串,StringBuff ...

  9. String详解

    在开发中,我们都会频繁的使用String类,掌握String的实现和常用方法是必不可少的,当然,我们还需要了解它的内部实现. 一. String的实现 在Java中,采用了一个char数组实现Stri ...

  10. C#String详解

    字符串:stringLength - 字符串的长度. TrimStart() 压缩空格即消除字符串开始空格TrimEnd() 消除结尾空格Trim() 同时消除开头和结尾空格.注:中间空格不消除,因为 ...

随机推荐

  1. 1083 List Grades

    Given a list of N student records with name, ID and grade. You are supposed to sort the records with ...

  2. windows黑窗口命令笔记

    windows有个黑窗口,吃惊吧!意外吧!! 哈哈,我是真的有些吃惊的!! nslookup ipconfig /all ipconfig /flushdns windows 声音修复 windows ...

  3. PE文件加节感染之Win32.Loader.bx.V病毒分析

    一.病毒名称:Win32.Loader.bx.V 二.分析工具:IDA 5.5.OllyDebug.StudPE 三.PE文件加节感染病毒简介 PE病毒感染的方式比较多,也比较复杂也比较难分析,下面就 ...

  4. 病毒木马查杀实战第017篇:U盘病毒之专杀工具的编写

    前言 经过前几次的讨论,我们对于这次的U盘病毒已经有了一定的了解,那么这次我们就依据病毒的行为特征,来编写针对于这次U盘病毒的专杀工具. 专杀工具功能说明 因为这次是一个U盘病毒,所以我打算把这次的专 ...

  5. 五、postman公共函数及newman运行与生成测试报告

    一.公共函数 postman中定义公共函数如下 1.每次断言的时候都需要重写或者复制之前的断言代码,可以通过如下方法定义断言的公共函数,以后每次断言的时候只需要调用公共函数即可进行断言 设置公共函数对 ...

  6. 在ZOHO企业网盘中如何快速搜索文件?

    现在越来越多的企业采用企业网盘来存储文档和资料,而且现在市面上的企业网盘各种各样.在使用企业网盘过程中,很多用户会问到企业网盘中如何快速搜索文件的问题.但是无论是"标签"功能还是普 ...

  7. Spring的Xml和JavaConfig 扩展你选哪一个?

    引言 上一篇文章我们有怎么介绍到如何通过XML的形式来定义Spring的扩展<Spring面试高频题如何:自定义XML schema 扩展>,好多人都在吐槽现在都什么年代了,xml还有人再 ...

  8. java基础——if和Swith的应用

    顺序结构 java的基本结构就是顺序结构,除非特别说明,否则就按照一句一句的执行 它是任何一个算法都离不开的基本算法结构 选择结构 if单选择 if双选择 if多选择 嵌套的if结构 switch多选 ...

  9. python 运算及注释

    """ 上面的两行代码,在2.0的python中,若想执行含有汉字的代码,是必不可少的,且两行代码必写在单个py文件最上方,之间不可有任何字节.且该两行代码,可在pych ...

  10. QT 资源链家暂存

    1.Qt右击菜单栏中文化 链接:https://blog.csdn.net/yangxiao_0203/article/details/7488967