zoukankan      html  css  js  c++  java
  • [go]string内存结构

    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 算法(字符串快速查找)

  • 相关阅读:
    Centos LNMP 安装日记
    记录一次开源工单系统
    搭建Lvs负载均衡群集
    使用yum配置lnmp环境(CentOS7.6)
    AWK的介绍学习
    Shell应用之网卡流量监测
    【NLP】RNN、LSTM、GRU
    【机器学习】Softmax及求导
    【PyTorch】使用中注意事项
    【实作】CNN-人脸表情识别
  • 原文地址:https://www.cnblogs.com/iiiiiher/p/12259162.html
Copyright © 2011-2022 走看看