• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

[go]string内存结构

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

string内存结构

Go string 实现原理剖析(你真的了解string吗)

//builtin包对string的描述

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. 

//A string may be empty, but not nil. 
//Values of string type are immutable.
type string string

- 默认零值是"" , 而不是nil
- 不可变(值存储在只读内存区)
- stings数据结构的定义: 
src/runtime/string.go: stringStruct (对外呈现string)

type stringStruct struct {
	str unsafe.Pointer  //str首地址
	len int             //str长度
}
// str构造过程: 先构造stringStruct,然后将stringStruct转为str返回

var s string
s = "mao"

func gostringnocopy(str *byte) string { // 跟据字符串地址构建string
	ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)} // 先构造stringStruct
	s := *(*string)(unsafe.Pointer(&ss))                             // 再将stringStruct转换成string
	return s
}
// []byte转string(转换需要一次内存拷贝)

func GetStringBySlice(s []byte) string {
    return string(s)
}

1. 根据切片长度申请足够内存地址空间
2. 构建string
3. 拷贝数据
// string转换[]byte(转换需要一次内存拷贝)


func GetSliceByString(str string) []byte {
    return []byte(str)
}

1.申请内存地址空间
2.拷贝数据
// 字符串拼接
str := "Str1" + "Str2" + "Str3"

性能较好: 
	新字符串的内存空间是一次分配完成的,
	所以性能消耗主要在拷贝数据上。

一个拼接语句的字符串编译时都会被存放到一个切片中,拼接过程需要遍历两次切片,
	1. 第一次遍历获取总的字符串长度,据此申请内存,
	2. 第二次遍历会把字符串逐个拷贝过去。

func concatstrings(a []string) string { // 字符串拼接
    length := 0        // 拼接后总的字符串长度

    for _, str := range a {
        length += length(str)
    }
    s, b := rawstring(length) // 生成指定大小的字符串,返回一个string和切片,二者共享内存空间

    for _, str := range a {
        copy(b, str)    // string无法修改,只能通过切片修改
        b = b[len(str):]
    }
    
    return s
}



func rawstring(size int) (s string, b []byte) { // 生成一个新的string,返回的string和切片共享相同的空间
	p := mallocgc(uintptr(size), nil, false)

	stringStructOf(&s).str = p
	stringStructOf(&s).len = size

	*(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}

	return
}
// 为什么字符串不允许修改?
像C++语言中的string,其本身拥有内存空间,修改string是支持的。
但Go的实现中,string**不包含内存空间,只有一个内存的指针**,
这样做的好处是string变得非常轻量,可以很方便的进行传递而不用担心内存拷贝。

因为string通常指向字符串字面量,**而字符串字面量存储位置是只读段,而不是堆或栈上,**
所以才有了string不可修改的约定。

[strings包][https://www.linkinstar.wiki/2019/06/20/golang/source-code/strings-go-source-code/]

ToUpper
Replace
Index

hashStr //use in Rabin-Karp algorithm.
indexRabinKarp

genSplit
countGeneric

Rabin-Karp 算法(字符串快速查找)


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
go语言环境安装(Windows)发布时间:2022-07-10
下一篇:
Go-结构体发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap