在这篇文章中,将对字符串进行展开。字符串是一串固定长度的字符连接起来的字符集合。go语言中的字符串使用utf-8编码。

字符串的存储结构

使用unsafe.Sizeof()打印字符串,可以发现它的长度是一个定值16,通过查看源码,我们知道string的结构如下:

type stringStruct struct {
	str unsafe.Pointer
	len int
}

字符串的实际存储是一个byte数组,length长度就是字符数组的长度。这里的byte数组存储的是字符串的utf-8的编码

字符串的遍历

  1. 通过for以字节码的方式遍历
package main

import (
	"fmt"
)

func main() {
	var aa = "你好"
	for i := 0; i < len(aa); i++ {
		fmt.Printf("%d ", aa[i])
	}
	fmt.Println()
}

// 运行结果
228 189 160 229 165 189

此处打印的结果为中文字符串在计算机内存中存储实际存储的值,数据类型为byte

  1. for range以rune的方式遍历
package main

import (
	"fmt"
)

func main() {
	var aa = "你好"
	for idx, val := range aa {
		fmt.Printf("%d, %d \n", idx, val)
	}
}
// 运行结果
0, 20320
3, 22909

这里的打印的值为中文字符串对用的unicode码值,数据类型为rune,for range内部封装了utf-8转unicode的逆运算。

查看字符串的内存存储

使用GDB工具对以下代码进行debug,查看内存中的数据,设定实现以下三个目标

  1. 查看字符串数据结构
  2. 查看字符串的长度
  3. 查看字符串内存中的存储的值
package main

import "fmt"

var ss string

func main() {
	ss = "hello"
	fmt.Println(ss)
}
如下图

字符串访问

package main

import "fmt"

func main() {
	var ch = "hello"

	val := ch[0]
	fmt.Printf("val的类型:%T \nval的值:%d\n", val, val)
}
// 运行结果
val的类型:uint8
val的值:104

因为字符串是只读的,不能通过下标修改其值

字符串和字节切片的相互转化

go内置了string转byte切片互转的函数

package main

import "fmt"

func main() {
	var ch = "hello world!"
	var val = []byte(ch)

	fmt.Println(val)

	var str = string(val)
	fmt.Println(str)
}
// 运行结果
[104 101 108 108 111 32 119 111 114 108 100 33]
hello world!

这里的转化不是将string结构体中指向的byte切片直接做赋值操作,而是通过copy实现的,在数据量比较大时,这里的转化会比较耗费内存空间。

喜欢请关注微信公众号“云端漫记", 持续为你更新