前言
在看一个底层库的的时候, 看到了一个比较奇怪的写法, 于是乎有了本文.
主要探讨两个问题:
1. 利用编译来判断 Golang 接口是否实现
2. 延伸出的 make 和 new 的区别
正文
1. 利用编译来判断 Golang 接口是否实现
看了一个底层通用链接池的库, 有这么一行代码:
var _ Pooler = new(WeightedRoundRobin)
需要解释的是: Pooler 是一个接口类型.
- type Pooler interface {
- // ...
- }
刚开始看是疑惑的, 为什么 new 了之后是要抛弃调?
后面发现这个是为了 验证某某接口是否被实现了?
多看了一些代码后发现很多地方有类似这样的写法.
至此 Get 到了.
解释: 如果说次接口没有被实现, 那么一方面 ide 会有红横线出现, 另一方面在编译的时候会出现报错. 两方面的提示来保证写底层代码的接口是有被实现的.
2. 延伸出的 make 和 new 的区别
和小伙伴讨论期间, 跑出了这么一个问题:"可以使用 go test 的方式, 去_test.go 文件中定义一个接口, 来判断就好了. 上文判断会存在浪费内存的情况"
这边两个点:
1.go test 的方式肯定是可行的.
但是并没法保证程序员会真的记住去执行进行检测 (非强制必须走的流程). 但是直接通过前文方式, 是会在编译的时候抛错的, 这个是必须走的流程, 所以更推荐前文的方式.
2.new 占内存?
new: 申请了内存, 但是不会将内存初始化, 只会将内存置零, 返回一个指针.
make: 申请了内存, 返回已初始化的结构体的零值.
回到正文, 虽然申请了内存, 但占的内存其实并不多, 并且在初始化后的一次 gc 中便会回收. 所以还好.
同时也不存在效率问题, 编译型语言, 你懂的.
同时验证一个 new 和取地址和 make 的区别的代码:
- func main() {
- a1 := new([]int)
- a2:= &[]int{}
- a3:= make([]int,0)
- fmt.Println(a1,a2,a3,a1==a1)
来源: http://www.tuicool.com/articles/YbYRFvb