Declare, create and initialize struct types
// Sample program to show how to declare and initialize struct types.
package main
import "fmt"
// example represents a type with different fields.
//示例表示具有不同字段的类型。
type example struct {
flag bool
counter int16
pi float32
}
func main() {
// Declare a variable of type example set to its
// zero value.
var e1 example
// display the value
fmt.Printf("%+v\n", e1)
// Declare a variable of type example and init using
// a struct literal.
e2 := example{
flag: true,
counter: 11,
pi: 3.14159,
}
// display the field values
fmt.Println("flag", e2.flag)
fmt.Println("counter", e2.counter)
fmt.Println("pi", e2.pi)
/*
{flag:false counter:0 pi:0}
flag true
counter 11
pi 3.14159
*/
}
Anonymous struct types
package main
import "fmt"
func main() {
// Declare a variable of an anonymous type and init
// using a struct literal.
e := struct {
flag bool
counter int16
pi float32
}{
flag: true,
counter: 10,
pi: 3.14159,
}
// Display the values.
fmt.Printf("%+v\n", e)
fmt.Println("Flag", e.flag)
fmt.Println("Counter", e.counter)
fmt.Println("Pi", e.pi)
/*
{flag:true counter:10 pi:3.14159}
Flag true
Counter 10
Pi 3.14159
*/
}
Named vs Unnamed types 命名类型和匿名类型
// Sample program to show how variables of an unnamed type can
// be assigned to variables of a named type, when they are
// identical.
package main
import "fmt"
// example represents a type with different fields.
type example struct {
flag bool
counter int16
pi float32
}
func main() {
// Declare a variable of an anonymous type and init
// using a struct literal.
e := struct {
flag bool
counter int16
pi float32
}{
flag: true,
counter: 10,
pi: 3.14159,
}
// Create a value of type example.
var ex example
// Assign the value of the unnamed struct type
// to the named struct type value.
// 分配未命名的struct类型的值。
// 到命名的struct类型值。
ex = e
// Display the values.
fmt.Printf("%+v\n", ex)
fmt.Printf("%+v\n", e)
fmt.Println("Flag", e.flag)
fmt.Println("Counter", e.counter)
fmt.Println("Pi", e.pi)
/*
{flag:true counter:10 pi:3.14159}
{flag:true counter:10 pi:3.14159}
Flag true
Counter 10
Pi 3.14159
*/
}
结构体类型排列
// go get honnef.co/go/structlayout/cmd/...
// Alignment is about placing fields on address alignment boundaries
// for more efficient reads and writes to memory.
// Sample program to show how struct types align on boundaries.
// https://github.com/dominikh/go-tools/tree/master/cmd/structlayout
// go get honnef.co/go/structlayout/cmd/...
//对齐方式是在地址对齐边界上放置字段。
//为了更有效地读写内存。
//示例程序,以显示结构类型如何在边界上对齐。
package main
import (
"fmt"
"unsafe"
)
// No byte padding. 没有字节填充。
type nbp struct {
a bool // 1 byte sizeof 1
b bool // 1 byte sizeof 2
c bool // 1 byte sizeof 3 - Aligned on 1 byte
}
// Single byte padding. 单个字节填充。
type sbp struct {
a bool // 1 byte sizeof 1
// 1 byte padding sizeof 2
b int16 // 2 bytes sizeof 4 - Aligned on 2 bytes
}
// Two byte padding.
type tbp struct {
a bool // 1 byte size 1
// 3 bytes padding size 4
b int32 // 4 bytes size 8 - Aligned on 2 bytes
}
// Four byte padding.
type fbp struct {
a bool // 1 byte size 1
// 7 bytes padding size 8
b int64 // 8 bytes size 16 - Aligned on 8 bytes
}
// Eight byte padding on 64bit Arch. Word size is 8 bytes.
// 在64位的Arch上有8个字节的填充。字大小是8个字节。
type ebp64 struct {
a string // 16 bytes size 16
b int32 // 4 bytes size 20
// 4 bytes padding size 24
c string // 16 bytes size 40
d int32 // 4 bytes size 44
// 4 bytes padding size 48 - Aligned on 8 bytes
}
// No padding on 32bit Arch. Word size is 4 bytes.
// To see this build as 32 bit: GOARCH=386 go build
type ebp32 struct {
a string // 8 bytes size 8
b int32 // 4 bytes size 12
c string // 8 bytes size 20
d int32 // 4 bytes size 24 - Aligned on 4 bytes
}
// No padding.
type np struct {
a string // 16 bytes size 16
b string // 16 bytes size 32
c int32 // 8 bytes size 40
d int32 // 8 bytes size 48 - Aligned on 8 bytes
}
func main() {
// structlayout -json github.com/ardanlabs/gotraining/topics/go/language/struct_types/advanced/example1 nbp | structlayout-pretty
var nbp nbp
size := unsafe.Sizeof(nbp)
fmt.Printf("SizeOf[%d][%p %p %p]\n", size, &nbp.a, &nbp.b, &nbp.c)
/* SizeOf[3][0xc42001408a 0xc42001408b 0xc42001408c] */
// =========================================================================
// structlayout -json github.com/ardanlabs/gotraining/topics/go/language/struct_types/advanced/example1 sbp | structlayout-pretty
var sbp sbp
size = unsafe.Sizeof(sbp)
fmt.Printf("SizeOf[%d][%p %p]\n", size, &sbp.a, &sbp.b)
/* SizeOf[4][0xc4200140c0 0xc4200140c2] */
// =========================================================================
// structlayout -json github.com/ardanlabs/gotraining/topics/go/language/struct_types/advanced/example1 tbp | structlayout-pretty
var tbp tbp
size = unsafe.Sizeof(tbp)
fmt.Printf("SizeOf[%d][%p %p]\n", size, &tbp.a, &tbp.b)
/* SizeOf[8][0xc4200140d0 0xc4200140d4] */
// =========================================================================
// structlayout -json github.com/ardanlabs/gotraining/topics/go/language/struct_types/advanced/example1 fbp | structlayout-pretty
var fbp fbp
size = unsafe.Sizeof(fbp)
fmt.Printf("SizeOf[%d][%p %p]\n", size, &fbp.a, &fbp.b)
/* SizeOf[16][0xc4200140e0 0xc4200140e8] */
// =========================================================================
// structlayout -json github.com/ardanlabs/gotraining/topics/go/language/struct_types/advanced/example1 ebp | structlayout-pretty
var ebp64 ebp64
size = unsafe.Sizeof(ebp64)
fmt.Printf("SizeOf[%d][%p %p %p %p]\n", size, &ebp64.a, &ebp64.b, &ebp64.c, &ebp64.d)
/* SizeOf[48][0xc42007a180 0xc42007a190 0xc42007a198 0xc42007a1a8] */
// =========================================================================
// structlayout -json github.com/ardanlabs/gotraining/topics/go/language/struct_types/advanced/example1 np | structlayout-pretty
var np np
size = unsafe.Sizeof(np)
fmt.Printf("SizeOf[%d][%p %p %p %p]\n", size, &np.a, &np.b, &np.c, &np.d)
/* SizeOf[40][0xc42007a1b0 0xc42007a1c0 0xc42007a1d0 0xc42007a1d4] */
}
// https://github.com/ardanlabs/gotraining/tree/master/topics/go/language/struct_types