一般程序员会认为内存如下图所示,是有一个个的字节组成,而CPU却不是这样看待的。
CPU把内存当作一块一块的,块的大小可以是2、4、8、16字节大小,因此CPU读取内存是一块一块读取的。(块的大小称为内存读取粒度)
假设CPU要读取一个int型4字节大小的数据,分两种情况讨论:

当数据从0字节开始时,CPU只需要读取一次内存即可取到数据。
当数据从1字节开始时,CPU读取数据就变得复杂了,因为数据没有在一个块内存储。这种情况下,CPU先访问内存读取0-3字节数据,在访问内存读取4-7字节数据,然后把0、5、6、7字节的数据去掉,合并1、2、3、4字节数据。这样的操作显然是浪费了很多性能,所以就有了字节对齐,以空间换时间。
默认对齐长度:编译器会有一个默认对齐长度,golang 中 64 为系统默认的对齐长度是 8 (这个默认值规则具体不清楚,后面再来补充)
package main
import (
"fmt"
"reflect"
)
type Data struct {
b byte
a int32
x int64
}
type Data1 struct {
b byte
x int64
a int32
}
func main() {
var d Data
t := reflect.TypeOf(d)
fmt.Println(t.Size(),t.Align())
var d1 Data
t1 := reflect.TypeOf(d1)
fmt.Println(t1.Size(),t1.Align())
}
----------
输出结果:
16 8
24 8
上面的内存结构如下所示:
d 的内存结构:
b---|aaaa|xxxx|xxxxd1的内存结构: b---|----|xxxx|xxxx|aaaa|----
## C 语言
C 语言对齐规则和 golang 一致,C 语言的默认对齐大小由编译器决定,我们也可以通过以下代码修改默认对齐大小。
非著名程序员,全栈开发工程师,长期专注系统开发与架构设计。
功能待开通!
gorm 简介 gorm 是 go 语言中实现的比较好的 ORM 包,且是国人开发的。项目地址 事故描述 Scan 是 gorm 提供的一个把数据库结果读取到 struct 的函数。定义如下: // Scan scan value to a struct func (s *DB) Scan(dest interface{}) *DB { return s.NewScope(s.Value).Set("gorm:query_destination", dest).callCallbacks(s.parent.callbacks.queries).db } 今天同事小张写代码的时候写了一个
三个工具介绍 go fmt是用来规范go文件格式,比如格式化单个文件 go fmt xxx.go goimports 用来检查导入包,导入依赖包,删除不依赖的包 gometalinter 集成go语言几乎所有检测工具,静态分析代码,包含功能如下 go vet -工具可以帮我们静态分析我们的源码存在的各种问题,例如多余的代码,提前return的逻辑,struct的tag是否符合标准等。 go tool vet --shadow -用来检查作用域里面设置的局部变量名和全局变量名设置一样导致全局变量设置无效的问题 gotype -类型检测用来检测传递过来的变量和预期变量类型一致 gotype -x
Go 语言的可移植性 Java 平台可移植性是众所都知的,Java 的可移植性依赖于其虚拟机 JVM,Java 实现了对不同平台的 JVM 的支持,那么一份 Java 代码就可以在各个平台上运行。而 Go 语言的可移植性也是依赖于其 runtime,runtime 去对接操作系统层,用户代码在 runtime 中运行,用户代码就不用去关心平台问题。 查看 Go 支持的OS和平台: > $ go version go version go1.11 darwin/amd64 liushuai@liushuaideMacBook-Pro ~/Documents/goProject/src
临时忽略掉struct中空字段 type User struct { Email string `json:"email"` Password string `json:"password"` } 当我们把用户信息返回给前端的时候显然需要忽略调Password 字段,则可以这样做: json.Marshal(struct{ *User Password bool `json:"password,omitempty"` }{ User:user, }) 临时添加额外字段 type User struct { Email string `json:"
golang中字符串格式化输出 package main import ( "fmt" "os" ) type point struct { x, y int } func main() { // Go提供了几种打印格式,用来格式化一般的Go值,例如 // 下面的%v打印了一个point结构体的对象的值 p := point{1, 2} fmt.Printf("%v\n", p) // 如果所格式化的值是一个结构体对象,那么`%+v`的格式化输出 // 将包括结构体的成员名称和值 fmt.Printf("%