一、介绍

在没有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

如果是返回值的话,我们调用这个函数,还得进行返回值的类型转换,这对于调用方,无疑是巨大负担。
但作为参数,对于调用方,是巨大的便利,他可以传入各种类型。


海生
104 声望32 粉丝

与黑夜里,追求那一抹萤火。