5.6.1.3. 可选参数函数
Go语言不支持直接创建具有多个不同类型的可选参数函数。但是,我们可以使用特殊的函数struct并依赖Go语言可以将所有的值都初始化为其类型的零值来实现。
假如我们有一个用于处理某些自定义数据的函数,其中默认是处理所有的数据,但在某些情况下,我们希望能够指定要处理的第一和最后一项数据,是否记录函数的操作,并为无效数据提供错误处理函数。
要做到这一点,我们可以创建一个函数ProcessItems(items Items, first, last int, audit bool, errorHandler func(item Item)),last值为0意味着取items的最后一项而不管其索引值是多少,errorHandler函数只有在不为nil时才会被调用。也就是说,如果我们想要执行默认的操作,只需要ProcessItems(items,0,0,false,nil)即可。
一种更好的方法是创建一个Process-Items(items Items, options Options)函数,其中struct类型的Options含有参数值,这些参数值已被初始化为它们各自类型的零值,对函数的调用将简化为ProcessItems(items,Options{})。这样,当我们需要函数执行不同的操作时,只需要指定Options中字段的值即可。(稍后我们将介绍struct结构体。)让我们以Options结构体开始来看一下代码。
1 2 3 4 5 6 | type Options struct { First int // First item to process Last int // Last item to process (0 means process all from First) Audit bool // If true all actions are logged ErrorHandler func(item Item) // Called for each bad item if not nil } |
结构体可以聚合或嵌入任意类型的一个或多个字段。(第6章将会介绍聚合和嵌入之间的区别。)在这里,Options结构体聚合了两个int类型的字段,一个bool类型的字段和一个具有func(Item)签名的函数(即,函数引用)字段,其中Item是自定义类型(在本例中是自定义类型Items中的一个项)。
1 2 3 | ProcessItems(items, Options{}) errorHandler := func(item Item) { log.Println("Invalid:", item) } ProcessItems(items, Options{Audit: true, ErrorHandler: errorHandler}) |
上面的代码片段调用了两次自定义的ProcessItems() 函数。第一次调用使用了默认参数(即,处理所有数据,不记录任何操作,也不调用错误处理程序函数);在第二个调用中,创建了一个Options值,其中First和Last的值为0(告诉函数处理所有数据),覆写Audit和ErrorHandler的值,以便在数据无效时调用错误处理函数处理。
这种使用结构体实现可选参数函数的做法在Go语言的标准库中也有使用,例如,image.jpeg.Encode()函数。稍后我们还将在第6章中看到这种用法。