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

  • 相关阅读:
    Java基于Redis的分布式锁
    接口测试工具-Jmeter使用笔记(八:模拟OAuth2.0协议简化模式的请求)
    初识HttpRunner
    WebService接口测试
    git使用:本地分支merge到远程分支
    git使用:本地项目推送到gitlab
    模拟网络状况工具——clumsy
    JAVA学习笔记 (okHttp3的用法)
    JAVA学习笔记 (一、入门及前期准备)
    Jenkins+Jmeter持续集成笔记(五:问题优化)
  • 原文地址:https://www.cnblogs.com/iiiiiher/p/12259162.html
Copyright © 2011-2022 走看看