August 2021
Beginner to intermediate
450 pages
6h 1m
Chinese
有时我们需要写一个函数有能力统一处理各种值类型的函数,而这些类型可能无法共享同一个接口,也可能布局未知,也有可能这个类型在我们设计函数时还不存在,甚至这个类型会同时存在上面三种问题。
一个熟悉的例子是fmt.Printf中的格式化逻辑,它可以输出任意类型的任意值,甚至是用户自定义的一个类型。让我们先尝试用我们已学到的知识来实现一个类似的函数。为了简化起见,该函数只接受一个参数,并且与fmt.Sprint一样返回一个字符串,所以我们称这个函数为Sprint。
我们先用一个类型分支来判断这个参数是否定义了一个String方法,如果已定义则直接调用它。然后添加一些switch分支来判断参数的动态类型是否是基本类型(比如string、int、bool等),再对每种类型采用不同的格式化操作。
但我们如何处理类似[]float64、map[string][]string的其他类型呢?可以添加更多的分支,但这样的类型有无限种。更何况还有自己命名的类型,比如url.Values?因为即使我们有一个分支来处理map[string][]string(url.Vallues的底层类型),这个分支仍然不会处理url.Values,因为这两个类型不是完全一致的。更何况根本不可能引入url.Values的处理分支?因为这会导致库依赖于库的客户(即循环引用)。 ...