189 8069 5689

go语言sizeof Go语言中文网

GoLang内建类型 int 占多少字节

int is a signed integer type that is at least 32 bits in size. It is a distinct type, however, and not an alias for, say, int32.

站在用户的角度思考问题,与客户深入沟通,找到綦江网站设计与綦江网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都网站制作、成都做网站、企业官网、英文网站、手机端网站、网站推广、域名申请、网络空间、企业邮箱。业务覆盖綦江地区。

int 是带符号整数类型,其大小至少为32位。 它是一种确切的类型,而不是 int32 的别名。

int 不是int32,那 int 在内存站多少字节呢?官方没有明确,让我们测试下。

GOARCH="amd64"

package main

import (

"fmt"

"unsafe"

)

func main() {

i := int(1)

fmt.Println(unsafe.Sizeof(i)) // 4

j := 1

fmt.Println(unsafe.Sizeof(j)) // 4

u := uint(1)

fmt.Println(unsafe.Sizeof(u)) // 4

}

可以认为 int 是4字节么?我不敢这样认为,GoLang支持多种平台架构。如果对size有明确要求,那就用 int32 之类的吧。

补充:随Go版本的变化,这个的确是在变化,所以到底占用多少字节,还是看具体版本吧

Go语言中的字节序

Go中的binary包实现了简单的数字与字节序列的转换以及变长值的编解码

package main

import ( "fmt" "bytes" "encoding/binary" ) func main(){ n := 0x12345678 bytesBuffer := bytes.NewBuffer([]byte{}) //BigEndian 大端顺序存储 LittleEndian小端顺序存储 binary.Write(bytesBuffer, binary.BigEndian, int32(n)) data:=bytesBuffer.Bytes() fmt.Printf("[0]: %#x addr:%#x\n",data[0],data[0]) fmt.Printf("[0]: %#x addr:%#x\n",data[1],data[1]) fmt.Printf("[0]: %#x addr:%#x\n",data[2],data[2]) fmt.Printf("[0]: %#x addr:%#x\n",data[3],data[3]) }

输出

[0]: 0x12 addr:0xc042010248 [1]: 0x34 addr:0xc042010249 [2]: 0x56 addr:0xc04201024a [3]: 0x78 addr:0xc04201024b

也可以使用下面的方式

n := 0x12345678 var data []byte = make([]byte,4) //操作的都是无符号整型 binary.BigEndian.PutUint32(data,uint32(n))

可以使用下面的方式判断当前系统的字节序类型

const INT_SIZE int = int(unsafe.Sizeof(0))

//判断我们系统中的字节序类型 func systemEdian() { var i int = 0x1 bs := (*[INT_SIZE]byte)(unsafe.Pointer(i)) if bs[0] == 0 { fmt.Println("system edian is little endian") } else { fmt.Println("system edian is big endian") } }

golang 结构体 字节对齐是怎么样的

用golang解析二进制协议时,其实没必要管结构体的字段的对齐规则,何况语言规范也没有规定如何对齐,也就是没有规则。用encoding/binary.Read函数直接读入struct里就行,struct就像c那样写

type Data struct {

Size, MsgType uint16

Sequence uint32

// ...

}

golang编译器加不加padding,Read都能正常工作,runtime知道Data的布局的,不像C直接做cast所以要知道怎样对齐。

用unsafe.Alignof可以知道每个field的对齐长度,但没必要用到。

package main

/*

#include stdint.h

#pragma pack(push, 1)

typedef struct {

uint16_t size;

uint16_t msgtype;

uint32_t sequnce;

uint8_t data1;

uint32_t data2;

uint16_t data3;

} mydata;

#pragma pack(pop)

mydata foo = {

1, 2, 3, 4, 5, 6,

};

int size() {

return sizeof(mydata);

}

*/

import "C"

import (

"bytes"

"encoding/binary"

"fmt"

"log"

"unsafe"

)

func main() {

bs := C.GoBytes(unsafe.Pointer(C.foo), C.size())

fmt.Printf("len %d data %v\n", len(bs), bs)

var data struct {

Size, Msytype uint16

Sequence uint32

Data1 uint8

Data2 uint32

Data3 uint16

}

err := binary.Read(bytes.NewReader(bs), binary.LittleEndian, data)

if err != nil {

log.Fatal(err)

}

fmt.Printf("%v\n", data) // {1 2 3 4 5 6}

buf := new(bytes.Buffer)

binary.Write(buf, binary.BigEndian, data)

fmt.Printf("%d %v\n", buf.Len(), buf.Bytes()) // 15 [0 1 0 2 0 0 0 3 4 0 0 0 5 0 6]

}

Go 空结构体 struct{} 的使用

struct是Go中的关键字,用于定义结构类型。

例如:

struct {}是一个无元素的结构体类型,通常在没有信息存储时使用。优点是大小为0,不需要内存来存储struct {}类型的值。

struct {} {}是一个复合字面量,它构造了一个struct {}类型的值,该值也是空。

go中可以使用 unsafe.Sizeof 计算出一个数据类型实例需要占用的字节数。我们验证一下:

也就是说空结构体实例不占用任何内存空间。

Go 语言标准库没有提供 Set 的实现,通常使用 map 来代替。事实上,对于集合来说,只需要 map 的键,而不需要值。

声明为声明为 map[string]struct{} ,由于struct{}是空,不关心内容,这样map便改造为set 。

map可以通过“comma ok”机制来获取该key是否存在,例如 _, ok := map["key"] ,如果没有对应的值,ok为false。可以通过定义成 map[string]struct{} 的形式,值不再占用内存。其值仅有两种状态,有或无。如果定义的是 map[string]bool ,则结果有true、false或没有三种状态,而且即使是将值设置为 bool 类型,也会多占据 1 个字节。因此呢,将 map 作为集合(Set)使用时,可以将值类型定义为空结构体,仅作为占位符使用即可。

基于channels发送消息有两个重要方面:发了消息、发了什么消息。一个强调了通讯的发生,一个强调了通讯的内容。当我们更希望强调通讯发生的时刻时,我们将它称为 消息事件 。有些消息事件并不携带额外的信息,它仅仅是用作两个goroutine之间的同步,这时候我们可以用 struct{} 空结构体作为channels元素的类型。用来通知子协程(goroutine)执行任务,或只用来控制协程并发度。

在部分场景下,结构体只包含方法,不包含任何的字段。这时候我们就可以使用空结构体。

其实,上面的calculateInt 可以是任何类型,如 type calculateInt bool ,但是struct{}不占用任何空间,逻辑上也更合理,因此还是它最好。


文章名称:go语言sizeof Go语言中文网
当前URL:http://cdxtjz.cn/article/ddejiec.html

其他资讯