Go语言是否支持可选参数?还是我可以定义两个不同参数数量的同名函数?
Go语言是否支持可选参数?还是我可以定义两个不同参数数量的同名函数?
Go语言没有可选参数也不支持方法重载:
如果方法调度不需要进行类型匹配,它将变得更加简单。从其他编程语言的经验来看,使用相同名称但具有不同签名的各种方法有时很有用,但实践中也可能会导致混乱和脆弱性。只通过名称进行匹配并要求类型一致是Go类型系统中一个重要的简化决策。
make
是一个特例吗?还是它甚至并没有真正实现为一个函数... - mk12实现类似于可选参数的一个好方法是使用变长参数。函数实际上接收到的是你指定类型的切片。
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}
params
是一个整数切片。 - Ferguzz您可以使用一个包含参数的结构体:
type Params struct {
a, b, c int
}
func doIt(p Params) int {
return p.a + p.b + p.c
}
// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})
与省略号(params ...SomeType
)相比,主要优势在于您可以使用参数结构体(struct)来处理不同类型的参数。
对于任意数量、可能很大的可选参数,一个好的习惯是使用函数选项。
对于您的类型Foobar
,首先只编写一个构造函数:
func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
fb := &Foobar{}
// ... (write initializations with default values)...
for _, op := range options{
err := op(fb)
if err != nil {
return nil, err
}
}
return fb, nil
}
每个选项都是一个能够改变Foobar的函数。然后为用户提供方便的方法来使用或创建标准选项,例如:
func OptionReadonlyFlag(fb *Foobar) error {
fb.mutable = false
return nil
}
func OptionTemperature(t Celsius) func(*Foobar) error {
return func(fb *Foobar) error {
fb.temperature = t
return nil
}
}
为了简洁起见,您可以给选项的类型(游乐场)命名:
type OptionFoobar func(*Foobar) error
FooBar
是一个不透明的结构体类型,我不知道用户如何创建其他选项。如果 FooBar
不是不透明的,则函数选项的好处是无意义的,因为现在用户有两种初始化 FooBar
的方法:通过结构字面量或通过工厂函数(“构造函数”)。我的结论是,可选选项在选项集合被认为是封闭且由包作者控制时效果最佳。 - jub0bsOptionTemperatureForFoo
和OptionTemperatureForBar
?这难道不会使构造函数变得像NewFoo(OptionTemperatureForFoo(100), OptionReadonlyFlagForFoo(), OptionOtherForFoo())
这样难以理解吗?有什么方法可以改进这种情况吗? - undefined你可以使用一个映射(map)来传递任意命名的参数。如果这些参数具有不同类型,则需要使用“aType = map[key].(*foo.type)
”来断言类型。
type varArgs map[string]interface{}
func myFunc(args varArgs) {
arg1 := "default"
if val, ok := args["arg1"]; ok {
arg1 = val.(string)
}
arg2 := 123
if val, ok := args["arg2"]; ok {
arg2 = val.(int)
}
fmt.Println(arg1, arg2)
}
func Test_test() {
myFunc(varArgs{"arg1": "value", "arg2": 1234})
}
我感觉我来晚了,但我在搜索是否有比我已经做的更好的方法。这种方法解决了您尝试解决的问题,并提供了可选参数的概念。
package main
import "fmt"
type FooOpts struct {
// optional arguments
Value string
}
func NewFoo(mandatory string) {
NewFooWithOpts(mandatory, &FooOpts{})
}
func NewFooWithOpts(mandatory string, opts *FooOpts) {
if (&opts) != nil {
fmt.Println("Hello " + opts.Value)
} else {
fmt.Println("Hello")
}
}
func main() {
NewFoo("make it work please")
NewFooWithOpts("Make it work please", &FooOpts{Value: " World"})
}
更新1:
添加了一个功能性示例,以展示功能与样例的区别
nil
以使用默认值。此外,选项可以在它们自己的结构中进行文档化,并且您可以创建预定义的选项集。我在 GitHub 客户端库和 go-cache 库等其他库中看到了这一点。 - theistGo语言不支持可选参数、默认值和函数重载,但你可以使用一些技巧来实现相同的功能。
下面分享一个例子,可以在一个函数中使用不同数量和类型的参数。这是一段简单易懂的代码,需要添加错误处理和一些逻辑。
func student(StudentDetails ...interface{}) (name string, age int, area string) {
age = 10 //Here Age and area are optional params set to default values
area = "HillView Singapore"
for index, val := range StudentDetails {
switch index {
case 0: //the first mandatory param
name, _ = val.(string)
case 1: // age is optional param
age, _ = val.(int)
case 2: //area is optional param
area, _ = val.(string)
}
}
return
}
func main() {
fmt.Println(student("Aayansh"))
fmt.Println(student("Aayansh", 11))
fmt.Println(student("Aayansh", 15, "Bukit Gombak, Singapore"))
}
如果您不想使用指针,可以使用它们并将其保留为nil:
func getPosts(limit *int) {
if optParam != nil {
// fetch posts with limit
} else {
// fetch all posts
}
}
func main() {
// get Posts, limit by 2
limit := 2
getPosts(&limit)
// get all posts
getPosts(nil)
}