基于 Go 语言的结构体序列化与反序列化实现

news/2025/1/4 12:19:56/文章来源:https://www.cnblogs.com/honghu0420/p/18646086

背景

在软件开发中,序列化和反序列化是常见的操作,尤其是在网络通信、数据存储以及分布式系统中。序列化是指将数据结构或对象转化为字节流的过程,而反序列化则是将字节流还原为原始的数据结构或对象。通过这种方式,可以方便地在不同的系统或组件之间传输和存储数据。

在 Go 语言中,虽然标准库提供了如 encoding/jsonencoding/gob 等序列化机制,但有时我们需要更精细地控制序列化过程,特别是处理二进制数据格式时。本文将介绍如何在 Go 语言中手动实现结构体的序列化与反序列化操作,以便对序列化过程进行更高效、灵活的控制。

目标

本文旨在实现一个简单的结构体序列化与反序列化示例,展示如何将结构体 Person 转换为字节流(序列化),并从字节流中恢复结构体(反序列化)。通过这种方式,开发者可以灵活地控制序列化的格式,以便在不同场景下使用。

实现

1. 结构体定义

我们首先定义一个简单的 Person 结构体,该结构体包含两个字段:NameAgeName 是一个字符串,Age 是一个无符号的 32 位整数。

type Person struct {Name string `json:"name"`Age  uint32 `json:"age"`
}

2. 序列化函数

序列化的目的是将结构体转化为字节流。在这个示例中,我们采用自定义的二进制格式进行序列化。具体实现如下:

func (p *Person) Marshall() (data []byte, err error) {// 计算名字的长度nameLen := len(p.Name)// 计算需要分配的内存空间n := 4 + nameLen + 4// 分配内存空间data = make([]byte, n)// 填充Name字段的长度binary.BigEndian.PutUint32(data[:4], uint32(nameLen))// 填充Name字段copy(data[4:], []byte(p.Name))// 填充Age字段binary.BigEndian.PutUint32(data[4+nameLen:], uint32(p.Age))return data, nil
}

序列化的过程包括以下几个步骤:

  • 首先,我们计算 Name 字段的长度,并在字节流的开头存储这个长度(使用 4 字节表示)。
  • 然后,将 Name 字符串转换为字节数组,并将其存储在字节流中。
  • 最后,将 Age 字段以 4 字节的二进制格式存储。

3. 反序列化函数

反序列化的目的是将字节流恢复为原始的结构体。具体实现如下:

func (p *Person) Unmarshall(data []byte) (err error) {// 恢复Name字段的长度nameLen := binary.BigEndian.Uint32(data[:4])// 恢复Name字段p.Name = string(data[4 : 4+nameLen])// 恢复Age字段p.Age = binary.BigEndian.Uint32(data[4+nameLen:])return nil
}

反序列化的过程:

  • 首先,从字节流中读取存储的 Name 字段的长度。
  • 然后,根据长度从字节流中提取出 Name 字段。
  • 最后,从字节流中提取出 Age 字段的值,并赋值给 Person 结构体。

4. 示例使用

为了验证序列化和反序列化的功能,代码的 main 函数演示了如何使用 MarshallUnmarshall 方法:

func main() {// 测试p := &Person{Name: "Test", Age: 10}data, _ := p.Marshall()// 打印序列化后的数据fmt.Println(data)// 反序列化p1 := &Person{}p1.Unmarshall(data)// 打印反序列化后的结果fmt.Println(*p1)
}

在这个例子中,我们首先创建了一个 Person 对象,并通过调用 Marshall 方法将其序列化为字节流。接着,我们通过调用 Unmarshall 方法将字节流反序列化为新的 Person 对象,并打印出结果。

5. 运行结果

[0 0 0 4 84 101 115 116 0 0 0 10]
{Test 10}

从运行结果可以看到:

  • 序列化后的字节流:[0 0 0 4 84 101 115 116 0 0 0 10],其中前 4 个字节表示 Name 的长度(4),接下来的 4 个字节是字符串 Name 的 ASCII 编码("Test"),最后 4 个字节是 Age 的值(10)。
  • 反序列化后的 Person 对象:{Test 10},表明反序列化过程成功地恢复了原始数据。

实际意义

1. 数据传输

序列化和反序列化操作是数据传输中必不可少的步骤。例如,在分布式系统中,服务之间可能需要通过网络传输数据,而网络传输通常需要以字节流的形式进行。通过自定义的二进制格式,能够提高数据传输的效率,减少带宽消耗。

2. 数据存储

在一些场景下,我们可能需要将数据存储在磁盘或数据库中。通过序列化操作,结构体的数据可以方便地保存为二进制格式,这样不仅节省存储空间,还能提高数据读取的效率。

3. 性能优化

相比 JSON 等文本格式,二进制序列化格式在处理大型数据时通常具有更高的性能,尤其是在网络传输和磁盘 I/O 操作中。Go 语言的 binary 包提供了高效的二进制数据操作接口,可以确保序列化和反序列化的效率。

总结

通过本文,我们展示了如何在 Go 语言中实现结构体的序列化与反序列化。通过自定义的二进制格式,我们可以更加高效地处理数据,尤其是在网络传输和存储场景中。虽然 Go 标准库提供了如 JSON 和 Gob 等高级库来处理数据序列化,但通过手动实现,我们能够精确控制数据的格式,满足特定需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/862338.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习基础理论————分布式训练(模型并行/数据并行/流水线并行/张量并行)

主要介绍Pytorch分布式训练代码以及原理以及一些简易的Demo代码 模型并行 是指将一个模型的不同部分(如层或子模块)分配到不同的设备上运行。它通常用于非常大的模型,这些模型无法完整地放入单个设备的内存中。在模型并行中,数据会顺序通过各个层,即一层处理完所有数据之后…

overleaf-Latex教程

1.领取免费服务器,推荐免费服务器(SanFengYun)见下图。2.安装宝塔面板,配置内网为127.0.0.1,访问外网地址。 3.可以在宝塔面板一键部署网站,输入自己的域名即可。 4.关键:安装docker,安装yum,设置github可以访问。 5.更换docker镜像,自带镜像无法访问 6.按照overleaf…

Sola的2024年度总结

前言 2024 这一年对我来说确实意义非凡,很想写点东西来记录一下这一年我的经历,算是第一次写年度总结了。 简短的记录一下我这一年。 现在?未来? 回忆起大一下最后一节体育课,体育老师让每个人想一个词来描述这个上半年,我给出的答案是 : 迷茫 。 现在来看,这个答案贯穿…

洛谷 P11487 「Cfz Round 5」Gnirts 10——题解

洛谷P11487「Cfz Round 5」Gnirts 10传送锚点摸鱼环节 「Cfz Round 5」Gnirts 10 题目背景 English statement. You must submit your code at the Chinese version of the statement.In Memory of \(\text{F}\rule{66.8px}{6.8px}\). 题目描述 题面还是简单一点好。给定 \(n, …

基于高德地图API在Python中实现地图功能的方法

本文介绍在高德开放平台中,申请、获取地图API的Key的方法;同时通过简单的Python代码,调取API信息,对所得Key的可用性加以验证~本文介绍在高德开放平台中,申请、获取地图API的Key的方法;同时通过简单的Python代码,调取API信息,对所得Key的可用性加以验证。首先,我们进入…

活动对象----active object

一.preface 近期学习QPC框架,其核心之一就是 actvie-object,活动对象的出现是为了解决并发(阻塞、数据竞争)问题。笔者这里做一篇笔记,方便日后回顾。 二.What is "active object"活动对象的组成框架代码如下点击查看代码 typedef struct Active Active; typedef …

新的一年,我决定拆解一个蓝牙接收器

哈哈,容我介绍一下,如果大家对电子感兴趣,可以看一下下面的图片,会经常更新优秀的原创文章。再次感谢每一个努力的电子爱好者。今天我们来拆解一个蓝牙接收器,首先我们需要有一个直观的印象。下图就是我们这次需要拆解的对象。我再想这么小的接收器,电路是怎么放进去得呢…

jfianl 如何定时某个时间点执行一个任务

如果我们需要在某个点执行一个任务,可以用使用以下方法,首先在操作之间先明白思路 参考技术来源:https://jfinal.com/doc/9-2 第一步,先安装包,因为 这是第三方包: <dependency> <groupId>it.sauronsoftware.cron4j</groupId> <artifactId>cr…

Window平台下Visual Studio版本和Qt构建kit 以及OpenCV的对应关系

1、VS版本、MSVC版本、工具集的对应关系 参考https://www.cnblogs.com/lidabo/p/183977552、Qt中的构建kit和MSVC的对应关系 qt中使用对应版本的kit必须安装对应版本的VS才能使用3、OpenCV的VC17文件夹和VS版本的对应关系 OpenCV中的VC17文件夹就是指用的VS2022编译的库,visua…

题解:AT_abc386_d [ABC386D] Diagonal Separation

分析题面,发现题目求的是是否存在一个白点被 \((1, 1)\) 和任意一个黑点围成的矩形内。 先将所有黑点按 \(x\) 坐标排序。 枚举所有的白点。 找到所有横坐标不比该白点横坐标小的所有黑点的纵坐标的最大值所属点。如果该点的纵坐标小于该白点的纵坐标:(蓝点代表题目中的白点…

【Miscellaneous】一道高质量的杂项题,涉及暴破、Cloakify-python2、零宽、emoji-AES等知识点

引言 下半年很忙,好久不做题,趁2025元旦放假整理一道高质量的题目,怀念一下繁忙的2024年。 题目 考虑到某公司的不分享精神或许会有版权之类的争端,文件链接以后就不放了。 名称:happymd5 提示:有好多奇奇怪怪的MD5值,这是用来干什么的呢。 Writeup(WP)题目附件cipher…

2025-01-01:优质数对的总数Ⅰ。用go语言,给定两个整数数组 nums1 和 nums2,分别长度为 n 和 m,以及一个正整数 k。 如果 nums1 数组中的元素 nums1[i] 能被

2025-01-01:优质数对的总数Ⅰ。用go语言,给定两个整数数组 nums1 和 nums2,分别长度为 n 和 m,以及一个正整数 k。 如果 nums1 数组中的元素 nums1[i] 能被 nums2 数组中的元素 nums2[j] 乘以 k 除尽,则称 (i, j) 为一个优质数对(其中 0 <= i <= n - 1,0 <= j …