Basic data size
Before this, let’s take a look at the data size occupied by the basic types in golang
So(unsafe.Sizeof(true), ShouldEqual, 1) So(unsafe.Sizeof(int8(0)), ShouldEqual, 1) So(unsafe.Sizeof(int16(0)), ShouldEqual, 2) So(unsafe.Sizeof(int32(0)), ShouldEqual, 4) So(unsafe.Sizeof(int64(0)), ShouldEqual, 8) So(unsafe.Sizeof(int(0)), ShouldEqual, 8) So(unsafe.Sizeof(float32(0)), ShouldEqual, 4) So(unsafe.Sizeof(float64(0)), ShouldEqual, 8) So(unsafe.Sizeof(""), ShouldEqual, 16) So(unsafe.Sizeof("hello world"), ShouldEqual, 16) So(unsafe.Sizeof([]int{}), ShouldEqual, 24) So(unsafe.Sizeof([]int{1, 2, 3}), ShouldEqual, 24) So(unsafe.Sizeof([3]int{1, 2, 3}), ShouldEqual, 24) So(unsafe.Sizeof(map[string]string{}), ShouldEqual, 8) So(unsafe.Sizeof(map[string]string{"1": "one", "2": "two"}), ShouldEqual, 8) So(unsafe.Sizeof(struct{}{}), ShouldEqual, 0)
- Although the bool type only has one digit, But it also needs to occupy 1 byte, because the computer is a byte unit
- 64 machine, an int occupies 8 bytes
- string type occupies 16 bytes, internal Contains a pointer to data (8 bytes) and the length of an int (8 bytes)
- The slice type occupies 24 bytes and internally contains a pointer to data (8 bytes) And the length of an int (8 bytes) and the capacity of an int (8 bytes)
- The map type occupies 8 bytes and is a pointer to the map structure
- Yes Use struct{} to represent an empty type. This type does not occupy any space. Use this as the value of the map. You can use the map as a set to use
byte alignment
in the structure The fields of are not compactly arranged in the memory, but are aligned by bytes. For example, if int occupies 8 bytes, it can only be written at an address that is a multiple of 8. As for why byte alignment is required, Mainly for efficiency reasons, but after reading the deeper principles on the Internet, I feel that it is not very reliable, so I won’t talk nonsense. If you are interested, you can study it yourself
// |x---| So(unsafe.Sizeof(struct { i8 int8 }{}), ShouldEqual, 1)
Simply encapsulate an int8 structure. Like int8, it only occupies 1 byte and has no extra space.
// |x---|xxxx|xx--| So(unsafe.Sizeof(struct { i8 int8 i32 int32 i16 int16 }{}), ShouldEqual, 12) // |x-xx|xxxx| So(unsafe.Sizeof(struct { i8 int8 i16 int16 i32 int32 }{}), ShouldEqual, 8)
The contents of the two structures are exactly the same. The order of the fields has been adjusted, saving 33% of the space.
// |x---|xxxx|xx--|----|xxxx|xxxx| So(unsafe.Sizeof(struct { i8 int8 i32 int32 i16 int16 i64 int64 }{}), ShouldEqual, 24) // |x-xx|xxxx|xxxx|xxxx| So(unsafe.Sizeof(struct { i8 int8 i16 int16 i32 int32 i64 int64 }{}), ShouldEqual, 16)
It should be noted here that int64 can only appear at addresses that are multiples of 8, so in the first structure, there are 4 consecutive bytes that are empty
type I8 int8 type I16 int16 type I32 int32 So(unsafe.Sizeof(struct { i8 I8 i16 I16 i32 I32 }{}), ShouldEqual, 8)
After renaming the type, the type The size has not changed
For more golang related knowledge, please visit thegolangtutorial column!