一文详解Go语言字符串

文章目录

Go语言字符串的本质

Go 语言字符串本质是指向一串一段只读的 UTF-8 字节序列的描述符

两个关键

  • 只读
  • UTF-8 编码的字节序列

内存结构

在 Go 的源码中(具体可见 runtime/string.go)

复制代码
type stringStruct struct {  
    str unsafe.Pointer  
    len int  
}
层面 原因 说明
UTF-8 编码 变长结构,无法安全修改部分字节 改动一个字节可能破坏整个字符
Go 语言设计 字符串不可变 保证安全、高效、可共享
修改方式 转为 []rune[]byte 才能进行内容更改

和其他类型的转换(内存结构的变化)

转\[\]rune

Unicode 规定"编号",UTF 编码规定"存法"。

Unicode 像身份证号体系,UTF 像不同格式的数据库存储规则。

转换方向 语法 说明
string → []rune runes := []rune(str) 将字符串解码成 Unicode 码点切片
[]rune → string str := string(runes) 将 Unicode 码点重新编码成 UTF-8 字符串
string → []rune 实现的具体逻辑见 func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune
内容 string \[\]rune 备注
每个字符占用 1~4 字节(UTF-8) 4 字节(int32) rune 固定 4 字节
是否分配新内存 ✅ 是 转换时分配新切片
可否修改 ✅ 可以 string 只读
是否引用同一底层数据 ❌ 否 ❌ 否 完全新分配
go 复制代码
func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune {  
    // two passes.  
    // unlike slicerunetostring, no race because strings are immutable.    n := 0  
    for range s {  
       n++  
    }  
  
    var a []rune  
    if buf != nil && n <= len(buf) {  
       *buf = [tmpStringBufSize]rune{}  
       a = buf[:n]  
    } else {  
       a = rawruneslice(n)  
    }  
  
    n = 0  
    for _, r := range s {  
       a[n] = r  
       n++  
    }  
    return a  
}

转 \[\]bytes

转换方向 操作 是否分配新内存 是否复制 安全性
string → []byte []byte(s) ✅ 是 ✅ 是 ✅ 安全
[]byte → string string(b) ✅ 是 ✅ 是 ✅ 安全

测试代码

go 复制代码
func string_impl() {
    s1 := "My name is 张朝阳"
    arr := []byte(s1)
    brr := []rune(s1)
    fmt.Printf("last byte %d\n", arr[len(arr)-1]) // string可以转换为[]byte或[]rune类型
    fmt.Printf("last byte %c\n", arr[len(arr)-1]) // %c以unicode字符进行输出
    fmt.Printf("last rune %d\n", brr[len(brr)-1])
    fmt.Printf("last rune %c\n", brr[len(brr)-1])
    L := len(s1)
    fmt.Printf("string len %d byte array len %d rune
    array len %d\n",L,len(arr),len(brr))
    for _,ele := range sl {
    	fmt.Printf("%c",ele)//按rune进行遍历输出
    }
    fmt.Println()
    for i := 0;i<L;i++ {
    	fmt.Printf("%c",s1[i])//[i]前面应该出现数组或切片,这里自动把string转成了[]byte(而不是[]rune)
    }
    fmt.Println()
    arr[0]=9
    // s1[0]=9·//字符串不能修改
    fmt.Println(utf8.RunecountInstring(s1),len([]rune(s1)))//查看string里有几个rune
}

和 C 语言 []char 的区别

[]char 本质是一个字节数组

特征 C语言 Go语言
内存管理 手动 自动
可变性 可变 不可变
结束符 \0结尾 存储长度
字符集 ASCII/手动UTF-8 默认UTF-8
标准库 <string.h> stringsbytesunicode/utf8
安全性 容易出错 更安全
性能 较高但需谨慎 略低但稳定
相关推荐
Reart11 分钟前
Leetcode 309.买卖股票的最佳时期含冷冻期(你也想成为股票高手吗o〃ω〃o,718)
后端
小小的木头人17 分钟前
Python 批量解析 Excel 经纬度,调用高德地图 API 获取中文地址
开发语言·python·excel
Reart25 分钟前
Leetcode 188.买卖股票的最佳时机4(718)
后端·算法
Reart41 分钟前
Leetcode 123.买卖股票的最佳时期3(内有随心谈,718)
后端·算法
只与明月听1 小时前
LangChain 学习-掌握LangChain Core API
前端·人工智能·后端
nzz_1712141 小时前
PHP程序员转型AI岗位指南:核心技能、北京就业市场与转型路径分析
开发语言·人工智能·php
无相求码1 小时前
数组越界为什么有时候不崩溃?VS2013 下栈上变量的幽灵布局解密
c语言·后端
Risehuxyc1 小时前
C# 将doc转换为docx
开发语言·c#·xhtml
多加点辣也没关系2 小时前
JavaScript|第24章:事件循环与并发模型
开发语言·javascript·ecmascript
HONG````3 小时前
HarmonyOS ArkUI Image 组件完全指南:objectFit、占位图与加载回调
后端