go中string的底层是如何实现的

这篇具有很好参考价值的文章主要介绍了go中string的底层是如何实现的。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今天来了解一下go语言的string的底层是怎么实现的,我们知道java的string是一个类实现的,其实go也是类似的,go使用结构体实现了string。

string的底层实现

go的string源码位于src/runtime/string.go中,通过stringStruct定义了string的数据结构

type stringStruct struct {
	str unsafe.Pointer
	len int
}

当我们在赋值一个字符串的时候发生了什么?

var str string
str = "helo"

因为底层是是靠结构体构建的,所以在构建过程中是根据字符串构建stringStruct,在转化为string

//go:nosplit
func gostringnocopy(str *byte) string { // 根据传进来的字符串地址构建string
	ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)} // 构建stringStruct结构体
	s := *(*string)(unsafe.Pointer(&ss)) // 将结构体转化为string字符串
	return s
}

那么string转化为[]byte过程发生了什么呢?

具体转换过程如下

// The constant is known to the compiler.
// There is no fundamental theory behind this number.
const tmpStringBufSize = 32

type tmpBuf [tmpStringBufSize]byte

func stringtoslicebyte(buf *tmpBuf, s string) []byte {
	var b []byte
	if buf != nil && len(s) <= len(buf) {
		*buf = tmpBuf{}
		b = buf[:len(s)]
	} else {
		b = rawbyteslice(len(s))
	}
	copy(b, s)
	return b
}

定义了string缓冲大小是32,使用一个byte数组

当string长度 < 32时,使用一个byte数组接收即可

当string长度 > 32时,就要创建一个新的slice,就是那个rawbyteslice函数,我们来看一下rawbyteslice函数

// rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
func rawbyteslice(size int) (b []byte) {
	cap := roundupsize(uintptr(size))
	p := mallocgc(cap, nil, false)
	if cap != uintptr(size) {
		memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size))
	}

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

最后copy的执行是在切片中

// slicecopy is used to copy from a string or slice of pointerless elements into a slice.
func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen int, width uintptr) int {
	if fromLen == 0 || toLen == 0 {
		return 0
	}

	n := fromLen
	if toLen < n {
		n = toLen
	}

	if width == 0 {
		return n
	}

	size := uintptr(n) * width
	if raceenabled {
		callerpc := getcallerpc()
		pc := abi.FuncPCABIInternal(slicecopy)
		racereadrangepc(fromPtr, size, callerpc, pc)
		racewriterangepc(toPtr, size, callerpc, pc)
	}
	if msanenabled {
		msanread(fromPtr, size)
		msanwrite(toPtr, size)
	}
	if asanenabled {
		asanread(fromPtr, size)
		asanwrite(toPtr, size)
	}

	if size == 1 { // common case worth about 2x to do here
		// TODO: is this still worth it with new memmove impl?
		*(*byte)(toPtr) = *(*byte)(fromPtr) // known to be a byte pointer
	} else {
		memmove(toPtr, fromPtr, size)
	}
	return n
}

那么string转[]byte会发生内存拷贝吗?

从上面可以看出来,会发生内存拷贝,理论来说,类型强转都会发生内存拷贝。

但是能不能在转换的时候不发生内存拷贝呢?

答案是当然可以,通过底层结构转换,将string转化为底层结构体形式,再将这个结构体转换成切片的指针就好了文章来源地址https://www.toymoban.com/news/detail-600829.html

import (
 "fmt"
 "reflect"
 "unsafe"
)
 
func main() {
 str :="helo"
 strstruct := *(*reflect.StringHeader)(unsafe.Pointer(&str))
 b := *(*[]byte)(unsafe.Pointer(&strstruct))  
 fmt.Printf("%v",b)
}

到了这里,关于go中string的底层是如何实现的的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Golang】VsCode下开发Go语言的环境配置(超详细图文详解)

    📓推荐网站(不断完善中):个人博客 📌个人主页:个人主页 👉相关专栏:CSDN专栏、个人专栏 🏝立志赚钱,干活想躺,瞎分享的摸鱼工程师一枚 ​ 话说在前,Go语言的编码方式是 UTF-8 ,理论上你直接使用文本进行编辑也是可以的,当然为了提升我们的开发效率我们还是需

    2024年02月07日
    浏览(70)
  • 6.Go语言学习笔记-结合chatGPT辅助学习Go语言底层原理

    1、Go版本 2、汇编基础 推荐阅读:GO汇编语言简介 推荐阅读:A Quick Guide to Go\\\'s Assembler - The Go Programming Language 精简指令集 数据传输: MOV/LEA 跳转指令: CMP/TEST/JMP/JCC 栈指令: PUSH/POP 函数调用指令: CALL/RET 算术指令: ADD/SUB/MUL/DIV 逻辑指令: AND/OR/XOR/NOT 移位指令: SHL/SHR JCC有条件跳转: JE

    2024年02月04日
    浏览(34)
  • String底层函数的实现方式

    1. strcpy函数的实现 注意: strcpy  函数的返回值类型为  char* ,即目标字符串的起始地址,主要有以下两个原因: 方便链式表达式:通过返回目标字符串的指针,可以方便地在连续的字符串操作函数中进行链式调用。比如可以将  strcpy  与其他字符串操作函数(如  strcat )

    2024年02月10日
    浏览(21)
  • 【C++干货铺】剖析string | 底层实现

    ========================================================================= 个人主页点击直达: 小白不是程序媛 C++专栏: C++干货铺 代码仓库: Gitee ========================================================================= 目录 成员变量 成员函数 构造和拷贝构造 赋值重载 析构函数 operator[ ] size 迭代器  rese

    2024年02月05日
    浏览(27)
  • Golang Map底层实现简述

    Go的 map 是一种高效的数据结构,用于存储键值对。其底层实现是一个哈希表(hash table),下面是有关 map 底层实现的详细介绍: 哈希表 : map 的底层实现是一个哈希表,也称为散列表。哈希表是一个数组,其中每个元素被称为\\\"桶\\\",用于存储键值对。 哈希表的大小是可动态

    2024年02月08日
    浏览(35)
  • Golang:Go语言结构

    在我们开始学习 Go 编程语言的基础构建模块前,让我们先来了解 Go 语言最简单程序的结构。 Go 语言的基础组成有以下几个部分: 包声明 引入包 函数 变量 语句 表达式 注释 接下来让我们来看下简单的代码,该代码输出了\\\"Hello World!\\\": 让我们来看下以上程序的各个部分: 第一

    2024年02月10日
    浏览(50)
  • 遇到跨端开发或多项目开发时,遇到的一些问题探讨,后端开发语言如何选择?

    ​最近有同学问我,做后端开发项目时用php,java,c#,go,pathon...哪个好,从最近阿里云、美团服务器崩溃来看,我想给你最直接的回答是,没有完美的,只有适合自己的。咱们讨论最多的问题就是跨多端开发,以及多项目开发后期所带来的升级、维护等相关问题,接下来就

    2024年02月04日
    浏览(34)
  • 【C++杂货铺】探索string的底层实现

    string 本质上是一个动态顺序表,它可以根据需要动态的扩容,所以字符串一定是通过在堆上动态申请空间进行存储的,因此 _str 指向存储字符串的空间, _size 用来表示有效字符数, _capacity 用来表示可以存储有效字符的容量数。 注意 :默认构造函数需要注意的地方是:首先

    2024年02月11日
    浏览(32)
  • C++ stl容器string的底层模拟实现

    目录 前言: 1.成员变量 2.构造函数与拷贝构造函数 3.析构函数 4.赋值重载 5.[]重载 6.比较关系重载 7.reserve 8.resize 9.push_back,append和重载+= 10.insert 11.erase 12.find 14.迭代器 15.流插入,流提取重载 16.swap 17.c_str 18.完整代码+测试 总结: 1.成员变量 首先注意的就是_str,不能是const类型

    2024年04月23日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包