一、介绍
在没有any类型之前,go语言中,我们经常使用interface{},来表示一个类型是未知的,或者有好几种其他基础类型的情况。
从 Go1.18开始,go官方定义了一个预声明标识符(Predeclared identifiers):any。
// any is an alias for interface{} and is equivalent to interface{} in all ways.
// any 是一个 interface{}的 别名,并且在任何情况下和interface{}相同。
type any = interface{}
官方的定义,告诉了我们any就是interface{}的别名,用来代替interface{}的。
go源码中现在也大量的使用any比如:
func Print(a ...any) (n int, err error)
func Println(a ...any) (n int, err error)
type Pointer[T any] struct
var expunged = new(any)
dirty map[any]*entry
func Marshal(v any) ([]byte, error)
......
太多地方用到了,基本上go官方,用any代替了任何interface{}出现的地方。
二、any的最佳实践
2.1 在map的情况下,map更适合做key
我们先来看一个下面两个时间,大家比较一下,哪一个比较好。
func TestAny(t *testing.T) {
m1 := make(map[any]string, 0)
m1["1"] = "1"
m1[2] = "2"
var v1 string = m1["1"]
var v2 string = m1[2]
t.Log(v1, v2)
m2 := make(map[string]any, 0)
m2["1"] = "1"
m2["2"] = 2
var v3 string = m2["1"].(string)
var v4 int = m2["2"].(int)
t.Log(v3, v4)
}
结论是 m1这种方式好。为什么,因为用做key的话,这样我们无论做为保存,还是读取,都无需多做什么操作。
m2这种方式,我们需要拿到数据后,进行类型的转换。这一步还的和之前保存的一样,就很复杂。
2.2 函数的参数和返回值,any更适合做参数
在官方的json解析包里面。无论是编码还是解码,any都只是作为参数。
func Marshal(v any) ([]byte, error)
func Unmarshal(data []byte, v any) error
如果是返回值的话,我们调用这个函数,还得进行返回值的类型转换,这对于调用方,无疑是巨大负担。
但作为参数,对于调用方,是巨大的便利,他可以传入各种类型。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。