`
乱蓬头199303
  • 浏览: 81108 次
文章分类
社区版块
存档分类
最新评论

谈谈Go语言的字符串设计

go 
阅读更多

摘要: 本文来自:http://www.ttkmwl.com 最给力的程序源码下载论坛 -通天源码论坛 『问题描述』 那天有用户向我反馈在使用 GoJieba 的过程中发现内存泄露的Bug。 具体现象就是这个测试代码 test.go 跑着跑着内存一直增长。

本文来自:http://www.ttkmwl.com 最给力的程序源码下载论坛 -通天源码论坛

 

『问题描述』

那天有用户向我反馈在使用 GoJieba 的过程中发现内存泄露的Bug。 具体现象就是这个测试代码 test.go 跑着跑着内存一直增长。 刚开始以为是代码里面的C语言部分内存没有正确释放导致的, 查了很久一直没有找到问题所在。

最后发现这个Bug非常白痴,是因为 C.CString 使用不当导致的。 在调用了 C.CString 之后需要手动释放内存。 这个Bug非常白痴,但是却反映了我之前对Go语言string理解不彻底的隐患。 才导致在我第一眼看到 C.CString 的时候, 就下意识的认为这个函数肯定没有动态申请新的内存, 和 C++ string::c_str() 一样,复用了内存。 所以也就肯定不需要手动释放。 当然这些只是『我以为』。

『问题深扒』

C语言和Go语言本是同根生嘛, 所以Go语言在设计的时候就通过cgo对C语言调用支持得很好。 而Go语言和C语言之间的数据转换就是通过 C.CString (Go->C), C.GoString(C->Go) 来进行的。

先谈谈 C.GoString ,很显然当使用 C.GoString 的时候, 会复制C语言的*char指针指向的字符串的内容拷贝到Go语言的string管理的内存空间。 Go语言的string管理的内存空间有gc管理,不需要用户主动释放内存。 也就是不需要管它。

而 C.CString 将 Go语言 string 转换成 C语言字符串的时候。 我们就要谈谈为什么它不会像 C++ 的 string::c_str() 一样只是单纯的共用内存了。

本质原因在于对于 Go 来说, string 和 C语言最大的不同是: 在C语言中,字符串是以 ’\0’ 结尾。 其实我认为这个本身是一种历史遗留问题。

『C语言的字符串主要有两种存储方式可选』

比如一个 “hello” 的字符串。 我们在内存中表示可以有两种选择:

第一种:

第二种:

1

2

3

4

typedef struct {

    char* buffer;

    size_t len;

} string;

 

C语言默认的字符串选择了第一种方式, 我认为主要原因在于当年C语言发明的时候是内存和稀缺的时代。 第一种方式比第二种方式显然更省内存。

但是随着时代的发展,内存越来越便宜。内存已经越来越不是程序开发的瓶颈。 第二种方式越来越成为字符串设计的首选。 比如在Nginx之类的著名开源项目中,也是采用了第二种方式对字符串进行存储。

而第二种方式更受青睐的主要原因我认为有两点:

『1. 更好的内存共享』

比如有一个字符串s1 = “hello world” , 而有两种字符串s2 s3 分别是 s1 的子串:"hello", “world” . 当我们使用第二种方式存储字符串的时候, 我们对于s2 s3就直接复用 s1的内存即可。 无需动态分配和释放,这样的场景在协议解析,比如HTTP包头的场景下特别常用。

而假设我们使用第一种方式存储字符串的话, 那么 s1 = “hello world\0”, s2 = “hello\0”, 虽然 s2 是 s1 的子串,但是因为 “\0” 结尾符的存在, s2 就无法复用 s1 的内存,而是需要新申请一段新的内存。 这也是为什么在Go语言中, C.CString 函数返回的内存肯定是一段新的内存, 也就不得不要求调用者手动释放。

『2. 性能更高,获取长度不再是strlen这种O(N)时间复杂度的函数』

这点就比较显而易见了。

​​​​​​​

原文链接

分享到:
评论

相关推荐

    c 语言字符串逆序 c 语言字符串逆序

    c 语言字符串逆序 c 语言字符串逆序c 语言字符串逆序 c 语言字符串逆序c 语言字符串逆序 c 语言字符串逆序c 语言字符串逆序 c 语言字符串逆序c 语言字符串逆序 c 语言字符串逆序c 语言字符串逆序 c 语言字符串逆序c ...

    汇编语言字符串比较

    在汇编语言编程中,字符串比较是一个常见的任务,它涉及到字符序列的逐个对比来确定它们是否相等或包含关系。下面将详细讲解如何在汇编语言中实现这个功能。 首先,我们需要理解汇编语言的基本概念。汇编语言是一种...

    汇编语言课程设计--字符串匹配

    汇编语言课程设计--字符串匹配 本课程设计的主要目的是为了让学生增进对汇编语言的认识,加强用汇编语言编程的能力,掌握汇编语言的中断调用功能的应用,并了解和掌握汇编语言程序设计过程、方法及实现。课程设计的...

    汇编语言-字符串匹配

    在本课程设计中,我们聚焦于一个特定的应用场景:字符串匹配。字符串匹配是计算机科学中一个基础但至关重要的问题,广泛应用于文本处理、搜索引擎、数据安全等领域。在汇编语言中实现字符串匹配,能帮助我们深入理解...

    汇编语言实验字符串位置的查找

    ### 汇编语言实验:字符串位置的查找 本文将基于提供的汇编代码,解析如何在汇编语言中实现字符串的输入以及特定字符在该字符串中的位置查找。 #### 数据段 (DATAS) 数据段用于定义程序运行时所需的数据变量: ``...

    x86汇编语言文本字符串查找替换程序

    本文将深入探讨一个使用x86汇编语言编写的文本文件字符串查找与替换程序,以及其设计原理和操作步骤。 一、程序设计基础 1. 指令集:x86汇编语言基于80x86处理器的指令集,如MOV(数据传输)、CMP(比较)、JMP...

    C语言字符串转换为Python字符串的方法

    C语言字符串转换为Python字符串的方法 C语言字符串转换为Python字符串是指将C语言中的字符串数据转换为Python中的字符串对象,以便在Python环境中使用。下面详细介绍了C语言字符串转换为Python字符串的方法。 使用...

    C语言字符串练习(习题+答案).zip

    本资源"《C语言字符串练习(习题+答案).zip》"正是针对这一需求而准备的,它包含了C语言字符串操作的专项练习题和对应的答案,帮助学习者巩固和提升在字符串处理方面的技能。 字符串在C语言中扮演着重要角色,它们...

    C#字符串删除指定字符串|字符串删除子字符串

    在C#编程语言中,处理字符串是常见的任务之一,其中包括删除字符串中的特定部分或子字符串。本篇文章将详细探讨如何在C#中实现这一功能,包括多种方法和实用技巧。 首先,C#提供了多种内置方法来操作字符串,比如`...

    LabVIEW删除字符串中空格

    LabVIEW是一种图形化编程语言,由美国国家仪器公司(NI)开发,主要用于数据采集、测试测量和控制系统的设计。在LabVIEW中,处理字符串是常见的任务之一。本篇将详细讲解如何在LabVIEW中删除字符串中的空格以及计算...

    截取指定长度的字符串

    在实际应用中,我们可能还需要考虑一些边缘情况,例如当截取的长度超过了字符串的实际长度,这时通常会返回整个字符串或者空字符串,具体取决于编程语言的实现。 标签“字符串 截取”提示我们关注的重点在于理解和...

    C++课程设计之string字符串类

    C++课程设计之string字符串类 C++课程设计之string字符串类是C++程序设计中的一部分,主要是通过定义字符串类来实现对字符串的赋值、连接、复制、查找、交换操作。下面是相关的知识点: 一、字符串类的定义 在C++...

    Go-fuzzy提供类似SublimeTextVSCode等风格的模糊字符串匹配Go语言程序包

    "Go-fuzzy"是一个专为Go语言设计的程序包,它实现了类似Sublime Text和Visual Studio Code(VSCode)等流行代码编辑器的模糊字符串匹配功能。这种功能允许用户通过输入部分关键词快速查找和过滤目标字符串,极大地...

    TIA博途-字符转换为字符串以及截取字符串有效字符的具体方法示例.docx

    在处理通信数据时,我们经常需要对字符和字符串进行操作,例如将字符转换为字符串,或者从字符串中截取有效字符。以下将详细介绍在TIA博途中如何实现这些操作。 首先,字符转换为字符串的过程通常涉及到ASCII码。...

    统计字符串中子字符串出现的次数,并返回

    在IT领域,字符串处理是一项基础且重要的任务,尤其是在编程语言如C#中。"统计字符串中子字符串出现的次数,并返回"是一个常见的需求,广泛应用于文本分析、数据挖掘以及日志处理等多个场景。本篇文章将深入探讨如何...

    字符串查找与替换程序 文件

    同时,本文还将对Java语言中的字符串处理进行详细介绍。 字符串替换函数 字符串替换函数是一个常用的字符串处理函数,其主要功能是将指定字符串中指定的字符串替换为新的字符串。本函数的实现过程可以分为以下几个...

    C# 字符串转十六进制串,16进制反向转回原字符串

    字符串是由Unicode字符组成的序列,每个字符在计算机内部通常用16位(2个字节)来表示,可以是英文、数字、标点符号,甚至是中文等多语言字符。十六进制是一种逢16进1的方式,用于表示二进制数,它使用0-9和A-F这16...

    汇编语言字符串统计

    实验内容:从键盘输入一行字符,以‘$’结束,查找输入的字符串是否包含‘computer’字符串,如果包含,计算包含’computer’字符串的个数,并以十进制输出个数。 原理:输入一个字符串到定义好的空间string中,以’...

    C 语言 指针实现 字符串是否为回文

    根据给定的文件信息,我们可以总结出以下关于“C 语言 指针实现 字符串是否为回文”的详细知识点: ### C语言中的指针与字符串操作 #### 回文概念简介 在数学和计算机科学领域,一个字符串被称为回文(Palindrome...

    Go-stringish一组可链式字符串助手可减少操纵字符串的痛苦

    在Go语言中,字符串操作是常见的编程任务,但标准库提供的功能有时可能不足以满足所有需求。为了解决这个问题,开发者创建了"Go-stringish",一个可链式字符串处理库,旨在简化和优化字符串处理过程,减少代码中的...

Global site tag (gtag.js) - Google Analytics