golang中struct和[]byte的相互转换示例

在网络传输过程中,经常会这样处理:socket接收到数据,先获取其消息头,然后再做各种不同的业务处理。在解析消息头的时候的方法有多种多样。其中最为高效解析消息头的方法就是直接把数据头部分强制类型转换为对应的消息头结构体。这种做法在C/C++中非常的常见。而golang其实也是可以这样子做的。类似这样的应用,直接类型转换获取消息对应的解析方法其实效率会相对较高。

golang中struct和[]byte的转换方法,其实就是用到了golang中的unsafe包加上类型转换 , 约束:struct中不能有指针类型。

1、struct转化为[]byte,转换方法如下:

import (
  "fmt"
  "unsafe"
)
type TestStructTobytes struct {
  data int64
}
type SliceMock struct {
  addr uintptr
  len int
  cap int
}

func main() {

  var testStruct = &TestStructTobytes{100}
  Len := unsafe.Sizeof(*testStruct)
  testBytes := &SliceMock{
    addr: uintptr(unsafe.Pointer(testStruct)),
    cap: int(Len),
    len: int(Len),
  }
  data := *(*[]byte)(unsafe.Pointer(testBytes))
  fmt.Println("[]byte is : ", data)
}

运行结果:

[]byte is :  [100 0 0 0 0 0 0 0]

因为[]byte底层的数据结构为:

struct {
 addr uintptr
 len int
 cap int
 }

其中addr为数值的地址,len为当地数值的长度,cap为数值的容量。

转换的时候,需要定义一个和[]byte底层结构一致的struct(如例子中的SliceMock),然后把结构体的地址赋给addr,结构体的大小赋给len和cap。最后将其转换为[]byte类型。

2、将[]byte转换为struct,转换方法如下:

import (
  "fmt"
  "unsafe"
)
type TestStructTobytes struct {
  data int64
}
type SliceMock struct {
  addr uintptr
  len int
  cap int
}

func main() {

  var testStruct = &TestStructTobytes{100}
  Len := unsafe.Sizeof(*testStruct)
  testBytes := &SliceMock{
    addr: uintptr(unsafe.Pointer(testStruct)),
    cap: int(Len),
    len: int(Len),
  }
  data := *(*[]byte)(unsafe.Pointer(testBytes))
  fmt.Println("[]byte is : ", data)
  var ptestStruct *TestStructTobytes = *(**TestStructTobytes)(unsafe.Pointer(&data))
  fmt.Println("ptestStruct.data is : ", ptestStruct.data)
}

运行结果:

[]byte is :  [100 0 0 0 0 0 0 0]
ptestStruct.data is :  100

从上面的例子中将[]byte转换为struct的代码片段为:

var ptestStruct *TestStructTobytes = *(**TestStructTobytes)(unsafe.Pointer(&data))

分析: 

由于在golang中编译器不将[]byte视为指针,所以要使用其地址进行转换,由于[]byte底层存放的是指向数据的地址。用[]byte的地址就需要使用双层指针转换,然后再指向其内容,得出来的就是转换对应struct的指针了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Go开发Struct转换成map两种方式比较

    最近做Go开发的时候接触到了一个新的orm第三方框架gorose,在使用的过程中,发现没有类似beego进行直接对struct结构进行操作的方法,有部分API是通过map进行数据库相关操作,那么就需要我们把struct转化成map,下面是是我尝试两种不同struct转换成map的方法 mport ( "encoding/json" "fmt" "reflect" "time" ) type Persion struct { I

  • golang中struct和[]byte的相互转换示例

    在网络传输过程中,经常会这样处理:socket接收到数据,先获取其消息头,然后再做各种不同的业务处理.在解析消息头的时候的方法有多种多样.其中最为高效解析消息头的方法就是直接把数据头部分强制类型转换为对应的消息头结构体.这种做法在C/C++中非常的常见.而golang其实也是可以这样子做的.类似这样的应用,直接类型转换获取消息对应的解析方法其实效率会相对较高. golang中struct和[]byte的转换方法,其实就是用到了golang中的unsafe包加上类型转换 , 约束:struct中不

  • Golang中的错误处理的示例详解

    目录 1.panic 2.包装错误 3.错误类型判断 4.错误值判断 1.panic 当我们执行panic的时候会结束下面的流程: package main import "fmt" func main() { fmt.Println("hello") panic("stop") fmt.Println("world") } 输出: go run 9.go hellopanic: stop 但是panic也是可以捕获的,我们可

  • golang中set数据结构的使用示例

    目录 借助map实现 算法应用 借助map实现 golang中没有set数据结构,一般是通过map实现,因为map的key值是不能重复的 示例 type empty struct { } // golang中的set数据类型 func MakeGolangSet(){     // 首先,空结构体内存消耗为0,其它数据结构如布尔值等均存在内存消耗     var e empty     fmt.Printf("empty struct memory is %v\n", unsafe.S

  • 在Java中int和byte[]的相互转换

    之前的项目中,在Socket通信的时候需要传int类型的值,不过java中outputsteam貌似不能直接传int类型,只能传byte[],所以在这里记录一下int和byte[]互转的方法. /** * int转byte[] */ public static byte[] intToBytes(int i) { byte[] bytes = new byte[4]; bytes[0] = (byte) (i & 0xff); bytes[1] = (byte) ((i >> 8) &

  • golang中struct和interface的基础使用教程

    前言 本文主要给大家介绍了关于golang中struct和interface的相关内容,是属于golang的基本知识,下面话不多说了,来一起看看详细的介绍吧. struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套:go中的struct类型理解为类,可以定义方法,和函数定义有些许区别:struct类型是值类型. struct定义 type User struct { Name string Age int32 mess string } var user User

  • Golang中struct{}和struct{}{}的区别解析

    目录 struct {} struct {} {} 使用场景举例 首先说下Golang中的结构体,结构体是由一系列具有相同类型或不同类型的数据构成的数据集合,Golang中使用关键字struct来创建一个结构体,语法如下: typeStudentstruct { Name string } 下面定义一个Student结构体,例如: typeStudentstruct { name string } 然后声明一个Student类型的变量并赋值 var stu Student stu.name =

  • Golang中的Unicode与字符串示例详解

    背景: 在我们使用Golang进行开发过程中,总是绕不开对字符或字符串的处理,而在Golang语言中,对字符和字符串的处理方式可能和其他语言不太一样,比如Python或Java类的语言,本篇文章分享一些Golang语言下的Unicode和字符串编码. Go语言字符编码 注意: 在Golang语言中的标识符可以包含 " 任何Unicode编码可以标识的字母字符 ". 被转换的整数值应该可以代表一个有效的 Unicode 代码点,否则转换的结果就将会是 "�",即:一个

  • 在Golang中使用Redis的方法示例

    周五上班的主要任务是在公司老平台上用redis处理一个队列问题,顺便复习了一下redis操作的基础知识,回来后就想着在自己的博客demo里,用redis来优化一些使用场景,学习一下golang开发下redis的使用. Redis简单介绍 简介 关于Redis的讨论,其实在现在的后台开发中已经是个老生常谈的问题,基本上也是后端开发面试的基本考察点.其中 Redis的背景介绍和细节说明在这里就不赘述.不管怎么介绍,核心在于Redis是一个基于内存的key-value的多数据结构存储,并可以提供持久化

  • golang中defer的关键特性示例详解

    前言 大家都知道golang的defer关键字,它可以在函数返回前执行一些操作,最常用的就是打开一个资源(例如一个文件.数据库连接等)时就用defer延迟关闭改资源,以免引起内存泄漏.本文主要给大家介绍了关于golang中defer的关键特性,分享出来供大家参考学习,下面话不多说,来一起看看详细的介绍: 一.defer 的作用和执行时机 go 的 defer 语句是用来延迟执行函数的,而且延迟发生在调用函数 return 之后,比如 func a() int { defer b() return

  • golang中strconv.ParseInt函数用法示例

    本文实例讲述了golang中strconv.ParseInt函数用法.分享给大家供大家参考,具体如下: golang strconv.ParseInt 是将字符串转换为数字的函数,功能灰常之强大. 参数1 数字的字符串形式 参数2 数字字符串的进制 比如二进制 八进制 十进制 十六进制 参数3 返回结果的bit大小 也就是int8 int16 int32 int64 func ParseInt(s string, base int, bitSize int) (i int64, err erro

随机推荐