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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM