go 中 string 并发写导致的 panic

类型的一点变化

在Go语言的演化过程中,引入了unsafe.String来取代之前的StringHeader结构体,这是为了提供更安全和简洁的字符串操作方式。

旧设计 (StringHeader 结构体)

StringHeader注释发生了一点变动,被标注了 Deprecated,通过询问 GPT 得出了下面的内容。

旧的设计中,StringHeader 结构体被用来手动管理字符串的底层数据。这种方式虽然灵活,但涉及大量的unsafe操作,容易引发潜在的安全问题和内存泄露。

go 复制代码
package runtime

// Deprecated: Use unsafe.String or unsafe.StringData instead.
type StringHeader struct {
	Data uintptr
	Len int
}

新设计 (unsafe.String 方法)

新的设计引入了unsafe.String方法,这是一个高层次的封装,减少直接操作指针的需求,同时仍然保留了灵活性和性能。这种设计主要有以下几个优点:

go 复制代码
// String returns a string value whose underlying bytes
// start at ptr and whose length is len.
//
// The len argument must be of integer type or an untyped constant.
// A constant len argument must be non-negative and representable by a value of type int;
// if it is an untyped constant it is given type int.
// At run time, if len is negative, or if ptr is nil and len is not zero,
// a run-time panic occurs.
//
// Since Go strings are immutable, the bytes passed to String
// must not be modified afterwards.
func String(ptr *byte, len IntegerType) string
  1. 减少直接操作指针的风险: 通过提供高层次的接口,开发者不再需要手动操作指针,这大大降低了出错的风险以及潜在的安全漏洞。

  2. 更简洁地表达意图: 使用方法而不是结构体,使得代码读起来更简洁,意图更清晰。

  3. 内建更好的错误检查: 封装在方法内部,可以内建一些基本的错误检查和约束,进一步提升代码的安全性和健壮性。

panic 触发回放

按照旧的数据结构来构造变量,Len 的部分设置为 16,Data 所指的内存数据设置为 nil,把结构体的内存位置和字符串的内存对应起来,再通过 unsafe 进行类型强转。

main 方法中变量 name 金玉其外败絮其中,你在访问它的时候就会触发 panic。sonic 三方库属于结构体序列化的高性能库。

go 复制代码
type mock struct {  
    bytes uintptr  
    len   int  
}  
  
func BytesToString() string {  
    var ee *int  
    ptr := unsafe.Pointer(ee)  
    var s = mock{bytes: uintptr(ptr), len: 16}  
    return *(*string)(unsafe.Pointer(&s))  
}

func main() {  
    name := BytesToString()  
    if res, err := sonic.Marshal(name); err != nil {  
       fmt.Errorf("sonic marshal error: %v", err)  
    } else {  
       fmt.Println(len(res), string(res))  
    }
}
相关推荐
Imnobody4 分钟前
吴恩达 Prompt 工程课精讲③:三次迭代,解决 Prompt 的三大致命问题(JupyterLab 实战)
后端
MediaTea15 分钟前
Python 第三方库:Word Cloud(词云图生成)
开发语言·python
小龙报21 分钟前
《算法每日一题(1)--- 第31场蓝桥算法挑战赛》
c语言·开发语言·c++·git·算法·学习方法
千桐科技21 分钟前
qKnow 知识平台【开源版】安装与部署全指南
人工智能·后端
llz_11222 分钟前
五子棋小游戏
开发语言·c++·算法
qq_124987075323 分钟前
基于Spring Boot的高校实习实践管理系统(源码+论文+部署+安装)
java·spring boot·后端·毕业设计
liulilittle24 分钟前
在 Android Shell 终端上直接运行 OPENPPP2 网关路由配置指南
android·linux·开发语言·网络·c++·编程语言·通信
作伴25 分钟前
结合Apollo手动实现一个动态线程池jar包
后端·架构
该用户已不存在25 分钟前
7个没听过但绝对好用的工具
前端·后端
Java水解26 分钟前
KingbaseES SQL性能调优方案分享
后端·sql