做网站运营需要注意哪些问题/百度问答怎么赚钱
目标:充分理解string与[]bytes零拷贝转换的实现
先回顾下string与[]byte的基本知识
1. string与[]byte的数据结构
reflect包中关于字符串的数据结构
// StringHeader is the runtime representation of a string.type StringHeader struct {Data uintptrLen int}
Data指向的是某个数组的首地址
len代表数组的长度。
uintptr是一种特殊指针,下文会具体介绍
说明
- string是一个8位的byte的集合,通常代表utf-8文本(但不一定都是)
- string可以为empty但不能是nil
- string的值是不能改变的(因为底层是数组)
reflect包中关于[]bytes的数据结构
type SliceHeader struct {Data uintptrLen intCap int}
Data指向的就是byte数组
[]byte是一个指向byte类型数组的slice
可以看到stringStruct与slice区别是cap,说明[]bytes的值是可变的,因为底层是切片。而string的值是不能改变的(因为底层是数组)
2. 基本数据结构的空间大小以及内存对齐
bl := truefmt.Println("size of bool:", unsafe.Sizeof(bl))// 1i := 10fmt.Println("size of int:", unsafe.Sizeof(i)) // 8i32 := int32(10)fmt.Println("size of int32:", unsafe.Sizeof(i32)) // 4i64 := int64(10)fmt.Println("size of int64:", unsafe.Sizeof(i64)) // 8str := "xxx"fmt.Println("size of str:", unsafe.Sizeof(str)) // 16type xstruct struct {a boolb int32c string}xx := xstruct{true, 10, "hello"}fmt.Println("size of xx.a:", unsafe.Sizeof(xx.a)) // 1fmt.Println("size of xx.b:", unsafe.Sizeof(xx.b)) // 4fmt.Println("size of xx.c:", unsafe.Sizeof(xx.c)) // 16fmt.Println("size of xx:", unsafe.Sizeof(xx)) // 不是1+4+16=21,而是24,为什么呢?由于字节对齐// xx.a为一个字节,而实际存储时会占用一个"对齐系数"也就是8字节(对于64位机器,"对齐系数"是8字节);// xx.b为四个字节,所以1+4=5,放一个对齐系数(8字节),其余剩余部分用0补充// xx.c为16个字节,刚好放满2个对齐系数(16字节)。所以8+16=24字节
从代码中总结常见类型变量占用空间:
bool占1个字节
int32占4个字节
int与int64 占4字节(64位机器)
string占16个字节,其中包含2部分,第一部分unsafe.pointer占8字节,第二部分len int占8字节
struct结构体占用的空间,计算时需要考虑字节对齐,字节对齐的好处是减少cpu访问memory的此次,cpu读取memory最小单位是一个字长(8字节),从而提供访问内存性能。(具体细节请问google)
3. unsafe.pointer与uintptr
string与[]byte结构的定义出现了uintptr,并且unsafe.pointer通常用于类型转换,下面具体介绍2中指针类型。
- unsafe.pointer与uintptr都是指针,但又不是普通指针,经查阅指针分为三种类型,分别有:
1. *类型: 这是最常用的指针,名叫普通指针类型,用于传递对象地址,不能进行指针运算。
2. unsafe.Pointer:通用指针类型,用于转换不同类型的指针,不能进行指针运算,不能读取内存存储的值(必须转换到某一类型的普通指针)。
3. uintptr:用于指针运算. 本质是存储 `指针地址` 的int类型
- unsafe.Pointer类型有四个重要描述:
(1)任何类型的指针都可以被转化为Pointer
(2)Pointer可以被转化为任何类型的指针
(3)uintptr可以被转化为Pointer
(4)Pointer可以被转化为uintptr
简而言之,unsafe.Pointer可以实现指针类型的转换,uintptr用于指针计算
下面看看Pointer的内部结构:
type Pointer *ArbitraryType// ArbitraryType is here for the purposes of documentation only and is not actually// part of the unsafe package. It represents the type of an arbitrary Go expression.type ArbitraryType int
ArbitraryType是int的一个别名,在Go中对ArbitraryType赋予特殊的意义。代表一个任意Go表达式类型。
- unsafe.Pointer的使用示例:
value1 := int32(10)value2 := int64(12)p := &value1fmt.Println(reflect.TypeOf(p)) // *int32fmt.Println(*p) // 10//p = &value2 // 错误。 无法将p指向&value2地址,因为p是*int32类型,&value2是*ini64类型unsPtr := unsafe.Pointer(&value2) // 将*int64先转换为unsafe.Pointer类型指针,此时unsPtr指向&value2(也就是value2的地址)p = (*int32)(unsPtr) //转换为*int32指针类型fmt.Println(reflect.TypeOf(p)) // *int32fmt.Println(*p) // 11
- uintptr的使用示例
type student struct {name stringage uint8}s := student{name: "tom", // string类型,16字节age: 18, // int8类型,1字节}uptr := (uintptr)(unsafe.Pointer(&s)) // uptr指向结构体的首地址uptr = uptr + 16 // uptr移动16字节,指向age的地址age := *(*int8)(unsafe.Pointer(uptr)) // 转换为*int8类型的指针fmt.Printf("age=%d\n", age) // 18
- 对uinitptr与unsafe.Pointer有简单了解后,再看结构体内存对齐示例
type student struct {name stringage uint8city string}s := student{name: "tom", // string类型,16字节age: 18, // int8类型,1字节; 需要做内存对齐,独占一个字长,本身占一个字节,其余7个字节填充city: "shenzhen", // string类型,16字节}
结构体的内存空间占用情况:
代码验证结构体占用空间的总大小,以及每个成员占用空间大小:
// 结构体占用空间fmt.Println("size of s:", unsafe.Sizeof(s)) // 40// 计算变量的地址fmt.Printf("address of s.name: %p\n", &s.name) // 0xc00008c030--->转换为十进制824634294320fmt.Printf("address of s.age: %p\n", &s.age) // 0xc00008c040--->转换为十进制824634294336fmt.Printf("address of s.city: %p\n", &s.city) // 0xc00008c048--->转换为十进制824634294344// 打印内部变量的相对字符串首地址的偏移量fmt.Printf("offset of s.age:%d\n", unsafe.Offsetof(s.name)) // 0fmt.Printf("offset of s.age:%d\n", unsafe.Offsetof(s.age)) // 16fmt.Printf("offset of s.age:%d\n", unsafe.Offsetof(s.city)) // 24,计算方法是24=16+8
下面我们把s字符串再进一步“打开”,探索一下字符串内部
先将s字符串转换为*reflect.StringHeader, 并查看字符串内部Data,Len的值
x := (*reflect.StringHeader)(unsafe.Pointer(&s)) // 转换为*reflect.StringHeaderfmt.Printf("x.Data: %v\n", x.Data) // 17603737,这就是Data变量保存的具体值,其实是一个内存地址fmt.Println("type of x.Data:", reflect.TypeOf(x.Data)) // uintptrfmt.Printf("&x.Data: %p\n", &x.Data) // 0xc000100030fmt.Printf("x.Len: %v\n", x.Len) // 3, 字符串"tom"的长度fmt.Printf("&x.Len: %p\n", &x.Len) // 0xc000100038, 说明38-30=8,表示x.Data占8个字节
- 使用uintptr,计算出x.city的地址,再获取改地址的值
uptr := (uintptr)(unsafe.Pointer(&s)) // uptr指向结构体的首地址uptr = uptr + 16 + 8 // uptr移动16+8字节,指向address的地址city := *(*string)(unsafe.Pointer(uptr)) // 转换为*string类型的指针,再用*获取改地址的值,也就是x.city的值fmt.Printf("city=%s\n", city) // shenzhen
4.string与[]bytes零拷贝的实现
最后,有了基础知识后,我们再看看string与[]bytes零拷贝的实现
string转换为[]byte
// 内存零拷贝方式类型转换
func stringtobyte(s string) []byte {// &s转换为*reflect.StringHeadervar sptr *reflect.StringHeadersptr = (*reflect.StringHeader)(unsafe.Pointer(&s))var b []byte// &b转换为*reflect.SliceHeaderbptr := (*reflect.SliceHeader)(unsafe.Pointer(&b))// 填充*reflect.SliceHeader内的Data,Len,Capbptr.Data = sptr.Databptr.Len = sptr.Lenbptr.Cap = sptr.Lenreturn b
}
为了编译理解,将转换过去用图示表示
[]byte转换为string
// 内存零拷贝方式类型转换
func bytetostring(b []byte) string {var bptr *reflect.SliceHeaderbptr = (*reflect.SliceHeader)(unsafe.Pointer(&b))var s stringsptr := (*reflect.StringHeader)(unsafe.Pointer(&s))sptr.Data = bptr.Datasptr.Len = bptr.Lenreturn s
}
// 转换方法二
// 转换方法二
func String2Bytes(s string) []byte {sh := (*[2]uintptr)(unsafe.Pointer(&s))bh := [3]uintptr{sh[0], sh[1], sh[1]}return *(*[]byte)(unsafe.Pointer(&bh))
}func String2Bytes2(s string) []byte {// &s转换为unsafe.Pointer类型的指针,再转换为指向定长为2的uintptr数组的指针sh := (*[3]uintptr)(unsafe.Pointer(&s))// sh是一个指针,不能直接转换为*[]byte的指针,先转换为unsafe.Pointer,再转换为*[]byte指针;最后*取出指针指向的内容return *(*[]byte)(unsafe.Pointer(sh))
}
相关文章:

go关于string与[]byte再学深一点
目标:充分理解string与[]bytes零拷贝转换的实现 先回顾下string与[]byte的基本知识 1. string与[]byte的数据结构 reflect包中关于字符串的数据结构 // StringHeader is the runtime representation of a string.type StringHeader struct {Data uintptrLen int} …...

Qt 实战(7)元对象系统 | 7.4、属性系统:深度解析与应用
文章目录 一、属性系统:深度解析与应用1、定义属性2、属性系统的作用3、属性系统工作原理(1)Q_PROPERTY宏(2)moc 的作用(3)属性在元对象中的注册 4、获取与设置属性4.1、QObject::property()与Q…...

Docker核心技术:容器技术要解决哪些问题
云原生学习路线导航页(持续更新中) 本文是 Docker核心技术 系列文章:容器技术要解决哪些问题,其他文章快捷链接如下: 应用架构演进容器技术要解决哪些问题(本文)Docker的基本使用Docker是如何实…...

sklearn中的增量学习:特征提取的艺术
sklearn中的增量学习:特征提取的艺术 在机器学习领域,特征提取是构建有效模型的关键步骤。然而,并非所有数据集都适合一次性加载到内存中进行处理,尤其是在处理大规模数据集时。Scikit-learn(sklearn)提供…...

PostgreSQL 中如何处理数据的唯一性约束?
🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!📚领书:PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何处理数据的唯一性约束?一、什么是唯一性约束二、为什么要设置唯一性约束…...

VAE论文阅读
在网上看到的VAE解释,发现有两种版本: 按照原来论文中的公式纯数学推导,一般都是了解生成问题的人写的,对小白很不友好。按照实操版本的,非常简单易懂,比如苏神的。但是却忽略了论文中的公式推导ÿ…...

【数据分享】2013-2022年我国省市县三级的逐月SO2数据(excel\shp格式\免费获取)
空气质量数据是在我们日常研究中经常使用的数据!之前我们给大家分享了2000——2022年的省市县三级的逐月PM2.5数据和2013-2022年的省市县三级的逐月CO数据(均可查看之前的文章获悉详情)! 本次我们分享的是我国2013——2022年的省…...

【Jmeter】记录一次Jmeter实战测试
Jmeter实战 1、需求2、实现2.1、新建线程组2.2、导入参数2.3、新建HTTP请求2.4、添加监听器2.5、结果 1、需求 查询某个接口在高并发场景下的响应时间(loadtime),需求需要响应在50ms以内,接下来用Jmeter测试一下 Jmeter安装见文章《Jemeter安装教程&am…...

volatile,最轻量的同步机制
目录 一、volatile 二、如何使用? 三、volatile关键字能代替synchronized关键字吗? 四、总结: 还是老样子,先来看一段代码: 我们先由我们自己的常规思路分析一下代码:子线程中,一直循环&…...

在Linux、Windows和macOS上释放IP地址并重新获取新IP地址的方法
文章目录 LinuxWindowsmacOS 在Linux、Windows和macOS上释放IP地址并重新获取新IP地址的方法各有不同。以下是针对每种操作系统的详细步骤: Linux 使用DHCP客户端:大多数Linux发行版都使用DHCP(动态主机配置协议)来自动获取IP地址…...

Mamba-yolo|结合Mamba注意力机制的视觉检测
一、本文介绍 PDF地址:https://arxiv.org/pdf/2405.16605v1 代码地址:GitHub - LeapLabTHU/MLLA: Official repository of MLLA Demystify Mamba in Vision: A Linear AttentionPerspective一文中引入Baseline Mamba,指明Mamba在处理各种高…...

语音识别标记语言(SSML):自动标识中文多音字
好的,以下是完整的实现代码,包括导入库、分词、获取拼音和生成 SSML 标记的全过程: import thulac from pypinyin import pinyin, Style# 初始化 THULAC thu1 thulac.thulac(seg_onlyTrue)# 测试文本 text "银行行长正在走行。"…...

排序算法与复杂度介绍
1. 排序算法 1.1 排序算法介绍 排序也成排序算法(Sort Algorithm),排序是将一组数据,依照指定的顺序进行排序的过程 1.2 排序的分类 1、内部排序: 指将需要处理的所有数据都加载到**内部存储器(内存&am…...

Kafka介绍及Go操作kafka详解
文章目录 Kafka介绍及Go操作kafka详解项目背景解决方案面临的问题业界方案ELKELK方案的问题日志收集系统架构设计架构设计组件介绍将学到的技能消息队列的通信模型点对点模式 queue发布/订阅 topicKafka介绍Kafka的架构图工作流程选择partition的原则ACK应答机制Topic和数据日志…...

DAY05 CSS
文章目录 1 CSS选择器(Selectors)8. 后代(包含)选择器9. 直接子代选择器10. 兄弟选择器11. 相邻兄弟选择器12. 属性选择器 2 伪元素3 CSS样式优先级1. 相同选择器不同样式2. 相同选择器相同样式3. 继承现象4. 选择器不同权值的计算 4 CSS中的值和单位1. 颜色表示法2. 尺寸表示法…...

HTTPS 的加密过程 详解
HTTP 由于是明文传输,所以安全上存在以下三个风险: 窃听风险,比如通信链路上可以获取通信内容。篡改风险,比如通信内容被篡改。冒充风险,比如冒充网站。 HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议,…...

spring整合mybatis,junit纯注解开发(包括连接druid报错的所有解决方法)
目录 Spring整合mybatis开发步骤 第一步:创建我们的数据表 第二步:编写对应的实体类 第三步:在pom.xml中导入我们所需要的坐标 spring所依赖的坐标 mybatis所依赖的坐标 druid数据源坐标 数据库驱动依赖 第四步:编写SpringC…...

ClusterIP、NodePort、LoadBalancer 和 ExternalName
Service 定义 在 Kubernetes 中,由于Pod 是有生命周期的,如果 Pod 重启它的 IP 可能会发生变化以及升级的时候会重建 Pod,我们需要 Service 服务去动态的关联这些 Pod 的 IP 和端口,从而使我们前端用户访问不受后端变更的干扰。 …...

【Day1415】Bean管理、SpringBoot 原理、总结、Maven 高级
0 SpringBoot 配置优先级 从上到下 虽然 springboot 支持多种格式配置文件,但是在项目开发时,推荐统一使用一种格式的配置 (yml是主流) 1 Bean管理 1.1 从 IOC 容器中获取 Bean 1.2 Bean 作品域 可以通过注解 Scope("proto…...

Git之repo sync -c与repo sync -dc用法区别(四十八)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...

vite + vue3 + uniapp 项目从零搭建
vite + vue3 + uniapp 项目从零搭建 1、创建项目1.1、创建Vue3/vite版Uniapp项目1.2、安装依赖1.3、运行项目2、弹出 用户隐私保护提示 方法2.1、更新用户隐私保护指引 和 修改配置文件2.2、授权结果处理方法3、修改`App.vue`文件内容4、处理报`[plugin:uni:mp-using-component…...

在CentOS中配置三个节点之间相互SSH免密登陆
在CentOS中配置三个节点(假设分别为node1、node2、node3)两两之间相互SSH免密登陆,可以按照以下步骤进行: 一、生成密钥对 在所有节点上生成密钥对: 在每个节点(node1、node2、node3)上执行以…...

arm 内联汇编基础
一、 Arm架构寄存器体系熟悉 基于arm neon 实现的代码有 intrinsic 和inline assembly 两种实现。 1.1 通用寄存器 arm v7 有 16 个 32-bit 通用寄存器,用 r0-r15 表示。 arm v8 有 31 个 64-bit 通用寄存器,用 x0-x30 表示,和 v7 不一样…...

Java语言程序设计——篇五(1)
数组 概述数组定义实例展示实战演练 二维数组定义数组元素的使用数组初始化器实战演练:矩阵计算 💫不规则二维数组实战演练:杨辉三角形 概述 ⚡️数组是相同数据类型的元素集合。各元素是有先后顺序的,它们在内存中按照这个先后顺…...

【香橙派开发板测试】:在黑科技Orange Pi AIpro部署YOLOv8深度学习纤维分割检测模型
文章目录 🚀🚀🚀前言一、1️⃣ Orange Pi AIpro开发板相关介绍1.1 🎓 核心配置1.2 ✨开发板接口详情图1.3 ⭐️开箱展示 二、2️⃣配置开发板详细教程2.1 🎓 烧录镜像系统2.2 ✨配置网络2.3 ⭐️使用SSH连接主板 三、…...

集成学习在数学建模中的应用
集成学习在数学建模中的应用 一、集成学习概述(一)基知(二)相关术语(三)集成学习为何能提高性能?(四)集成学习方法 二、Bagging方法(一)装袋&…...

WebKit 的 Web SQL 数据库:现代浏览器的本地存储解决方案
WebKit 的 Web SQL 数据库:现代浏览器的本地存储解决方案 随着Web应用的不断发展,对本地存储的需求也日益增加。WebKit作为许多现代浏览器的核心引擎,提供了一种强大的本地存储解决方案:Web SQL 数据库。本文将详细探讨Web SQL 数…...

Yolo-World网络模型结构及原理分析(三)——RepVL-PAN
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1. 网络结构2. 特征融合3. 文本引导(Text-guided)4. 图像池化注意力(Image-Pooling Attention)5. 区域文本匹配&…...

代码随想录——一和零(Leetcode474)
题目链接 0-1背包 class Solution {public int findMaxForm(String[] strs, int m, int n) {// 本题m,n为背包两个维度// dp[i][j]:最多右i个0和j个1的strs的最大子集大小int[][] dp new int[m 1][n 1];// 遍历strs中字符串for(String str : strs){int num0 …...

力扣题解(组合总和IV)
377. 组合总和 Ⅳ 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 思路: 本题实质上是给一些数字,让他们在满足和是targ…...