中间件的使用
- group 里面use的中间件只能在注册的路由生效,否则会报错
- default 里面use无论任何请求都会生效
Go json
- 处理[]byte时候会自动进行base64编码,bind会自动解码
- []byte字段json解码时只能接受base64串
go test
初始化
- go test 会主动调用初始化
- 如果需要其他初始化需要使用TestMain()
覆盖率
go test -v -covermode=set -coverprofile=hint_test.out
压力测试
go test -bench .
语言知识点
- make函数如何不指定大小,默认都是0,包括chan,因此初始化map一定要指定大小
为什么Go中没有volatile
[!info] java中volatile的作用
- 保证可见性(Visibility):当一个变量被声明为
volatile
时,当一个线程修改了这个变量的值,其他线程能立即看到这个变量的最新值。这是因为volatile
变量的值会被立即写入主内存,并且其他线程读取该变量时会直接从主内存中读取,而不是从线程的本地缓存中读取。- 禁止指令重排序(Prevent Reordering):
volatile
关键字可以防止编译器对被声明为volatile
的变量进行指令重排序优化。这样可以确保程序的执行顺序符合程序员的预期。==但是这里并不保证原子性,不能直接上多写== 总的来说,volatile
关键字适用于那些多线程环境下一个线程写,多个线程读的简单场景,主要用于保证可见性和禁止指令重排序。
- 这个问题一般是写java问写go的,cpp的通常不会这样问
- Go 的基本设计思想是
"Do not communicate by sharing memory; instead, share memory by communicating."
,换言之,Go 并不推荐我们在内存中使用共享变量 flag 的形式来实现通信,而是利用 channel 来实现通信,核心的区别点是设计理念上的区别
json.RawMessage
- 用于有时候需要根据type在具体决定解析到哪个结构体的情况下使用,一般不用interface{},因为parse会出错,使用这个替代interface,然后使用Unmarshal直接解析不需要断言
type Obj struct {
Type ObjType `json:"type,omitempty"`
Property json.RawMessage `json:"property,omitempty"`
}
// 然后
func parseBlock(obj *Obj) (block *Block, err error) {
block = &Block{}
err = json.Unmarshal(obj.Property, block)
if err != nil {
return nil, err
}
return
}
需要make初始化结构体
- map
- chan
- 其他的类似切片的用不用都可以
格式化工具
源码阅读工具
- https://github.com/TrueFurby/go-callvis.git 或者
go install github.com/ofabry/go-callvis@latest
代码规范
- #代码规范
命名
- 包名称:
- Go 包名称应该简短并且只包含小写字母。由多个单词组成的包名称应全部小写。例如,包 tabwriter 不应该命名为 tabWriter 、 TabWriter 或 tab_writer
- 避免使用无意义的包名称,例如 util 、 utility 、 common 、 helper,很容易造成导入冲突
- 接收者命名(this指针的名称):
- 短(通常是一两个字母的⻓度) 类型本身的缩写 始终如一地应用于该类型的每个接收者
- 常量命名:
- 常量名称必须像 Go 中的所有其他名称一样使用 混合大写字母MixedCaps。导出常量以大写字母 开头,而未导出的常量以小写字母开头。常量名称不 应是其值的派生词,而应该解释值所表示的含义。
- ==不要使用非混合大写常量名称或带有 K 前缀的常量==。
- 在具有多个首字母缩写的名称中(例如 XMLAPI 因为它包含 XML 和 API ),给定首字母缩写中 的每个字母都应该具有相同的大小写,但名称中的每个首字母缩写不需要具有相同的大小写
- 在带有包含小写字母的首字母缩写的名称中(例如 DDoS 、 iOS 、 gRPC ),首字母缩写应该像在 标准中一样出现,除非你需要为了满足 导出 而更改第一个字母。在这些情况下,整个缩写词应 该是相同的情况(例如 ddos 、 IOS 、 GRPC )
- Get方法:
- 函数和方法名称不应使用 Get 或 get 前缀,除非底层概念使用单词“get”(例如 HTTP GET)。此 时,更应该直接以名词开头的名称,例如使用 Counts 而不是 GetCounts 。
- 变量名:
- 一般的经验法则是,名称的⻓度应与其范围的大小成正比,并与其在该范围内使用的次数成反比。在 文件范围内创建的变量可能需要多个单词
- ==除第一个单词外,每个单词都以大写字母开头==
- 函数接收者变量:
- 使用一个字母或两个字母的名称。
[!tip] 参考 https://github.com/xxjwxc/uber_go_guide_cn 社区认可的 https://gocn.github.io/styleguide/docs/01-overview/ google的 effect-go GO官方的
如何避免Go语言的100个错误
错误检查工具
- vet 标准Go分析工具
- kisielk/errcheck 错误检查工具
- fzipp/gocyclo 循环复杂度分析工具
- goconst 重复字符串常量分析工具
切片注意事项
s1 := make([]int, 3, 6)
s2 := s1[1:3]
- 执行插入一个元素后,这个对于锁
- 是不可见的,因为s2的len没有改变
s2 = append(s2, 2)
// 此时
s1=[0 1 0], s2=[1 0 2]
- 插入多个元素后会地址发生改变
for注意事项
- 下面这个example中 v 会进行复用,因此每次获得的 v 的地址是完全相同的
type A struct {
A string
}
func ForTest() {
testData := []A{
{"1"}, {"2"},
}
target := []*A{}
for _, v := range testData {
target = append(target, &v)
}
log.V2.Info().Obj(target).Emit()
}
// [0xc0002cb470 0xc0002cb470]
// [{"A":"2"},{"A":"2"}]
下载最新版本Go
- 卸载原来的go
apt remove golang-go
- 下载安装包从Go下载 - Go语言中文网 - Golang中文社区
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.14.3.linux-amd64.tar.gz
版本自己更改export PATH=$PATH:/usr/local/go/bin
添加目录
gin
middleware顺序
- middleware的顺序是按照注册的顺序正序执行,而不是倒序执行