go语言字符串类型储存解析

在这篇文章中,将对字符串进行展开。字符串是一串固定长度的字符连接起来的字符集合。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实现的,在数据量比较大时,这里的转化会比较耗费内存空间。

原文发布于微信公众号 - 云端漫记(BB_gzhsh)

原文发表时间:2019-08-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券