我有一个函数可以解决Go不允许在方法声明中设置默认值的问题。我想通过允许可变数量的返回变量来使它更好一些。我知道我可以允许一个接口数组作为返回类型,然后创建一个包含所有要返回的变量的接口数组,如下所示:
func SetParams(params []interface{}, args ...interface{}) (...[]interface{}) {
var values []interface{}
for i := range params {
var value interface{}
paramType := reflect.TypeOf(params[i])
if len(args) < (i + 1) {
value = params[i]
} else {
argType := reflect.TypeOf(args[i])
if paramType != argType {
value = params[i]
}
value = args[i]
}
values = append(values, value)
}
return values
}
这是您要为其定义默认值的方法的示例。您将其构建为可变参数函数(允许可变数量的参数),然后在函数内而不是在声明行中定义要查找的特定参数的默认值。
func DoSomething(args ...interface{}) {
//setup default values
str := "default string 1"
num := 1
str2 := "default string 2"
//this is fine
values := SetParams([]interface{str, num, str2}, args)
str = values[0].(string)
num = values[1].(int)
str = values[2].(string)
//I'd rather support this
str, num, str2 = SetParams(params, args)
}
我理解
上例中的[] interface {str,num,str2}
在语法上不正确。我这样做是为了简化我的帖子。但是,它代表了构建接口数组的另一个函数。
我想支持这个:
str, num, str2 = SetParams(params, args)
而不是必须这样做:
values := SetParams([]interface{str, num, str2}, args)
str = values[0].(string)
num = values[1].(int)
str = values[2].(string)
有什么建议吗?帮助
答案 0 :(得分:3)
请不要写出可怕的(由于reflect
)代码来解决不存在的问题。
如评论中所示,将语言转换为
您以前的一种语言确实引人注目
切换后,但这会适得其反。
相反,最好使用习语和方法 和语言提供的最佳实践 - 即使你不喜欢它们(但也许)。
对于这种特殊情况,你可以像这样滚动:
制作想要接受的功能
具有默认值的参数列表
接受自定义struct
类型的单个值。
首先,任何此类型的变量在分配时, 将所有字段的所有字段初始化为所谓的“零值” 适合各自的类型。
如果这就够了,你可以在那里停下来:你将能够
将struct
类型的值传递给您的函数
通过在呼叫站点的文字生成它们 -
只初始化你需要的字段。
否则有预处理/后处理代码 将为字段提供您自己的“零值” 你需要。
2016-08-29更新:
使用struct
类型模拟可选参数
使用其字段分配发生的默认值
成为各自数据类型的Go的原始零值:
package main
import (
"fmt"
)
type params struct {
foo string
bar int
baz float32
}
func myfun(params params) {
fmt.Printf("%#v\n", params)
}
func main() {
myfun(params{})
myfun(params{bar: 42})
myfun(params{foo: "xyzzy", baz: 0.3e-2})
}
输出:
main.params{foo:"", bar:0, baz:0}
main.params{foo:"", bar:42, baz:0}
main.params{foo:"xyzzy", bar:0, baz:0.003}
如您所见,Go初始化params
类型的字段
零值适合各自的类型
除非我们在定义文字时指定自己的值。
提供非Go-native零值的默认值 我们的自定义类型的字段可以通过预先完成 或者后处理用户提交的复合类型值。
后处理:
package main
import (
"fmt"
)
type params struct {
foo string
bar int
baz float32
}
func (pp *params) setDefaults() {
if pp.foo == "" {
pp.foo = "ahem"
}
if pp.bar == 0 {
pp.bar = -3
}
if pp.baz == 0 { // Can't really do this to FP numbers; for demonstration purposes only
pp.baz = 0.5
}
}
func myfun(params params) {
params.setDefaults()
fmt.Printf("%#v\n", params)
}
func main() {
myfun(params{})
myfun(params{bar: 42})
myfun(params{foo: "xyzzy", baz: 0.3e-2})
}
输出:
main.params{foo:"ahem", bar:-3, baz:0.5}
main.params{foo:"ahem", bar:42, baz:0.5}
main.params{foo:"xyzzy", bar:-3, baz:0.003}
预处理相当于创建“构造函数”功能 这将返回预填充所需类型的值 使用默认值选择其字段 - 某些内容 像这样:
func newParams() params {
return params{
foo: "ahem",
bar: -3,
baz: 0.5,
}
}
以便您的函数的调用者可以调用newParams()
,
如果需要调整其字段,然后传递结果值
你的职能:
myfunc(newParams())
ps := newParams()
ps.foo = "xyzzy"
myfunc(ps)
这种方法可能比后处理更有效但是 它排除了使用文字来构造要传递给的值 你在呼叫站点的功能不那么“整洁”。
答案 1 :(得分:0)
最近,我在Go中使用匿名函数,并实现了一个接受并返回未定义参数的示例:
func functions() (funcArray []func(args ... interface{}) (interface{}, error)) {
type ret struct{
first int
second string
third bool
}
f1 := func(args ... interface{}) (interface{}, error){
a := args[0].(int)
b := args[1].(int)
return (a < b), nil
}
funcArray = append(funcArray , f1)
f2 := func(args ... interface{}) (interface{}, error){
return (args[0].(string) + args[1].(string)), nil
}
funcArray = append(funcArray , f2)
f3 := func(args ... interface{}) (interface{}, error){
return []int{1,2,3}, nil
}
funcArray = append(funcArray , f3)
f4 := func(args ... interface{}) (interface{}, error){
return ret{first: 1, second: "2", third: true} , nil
}
funcArray = append(funcArray , f4)
return funcArray
}
func main() {
myFirst_Function := functions()[0]
mySecond_Function := functions()[1]
myThird_Function := functions()[2]
myFourth_Function := functions()[3]
fmt.Println(myFirst_Function(1,2))
fmt.Println(mySecond_Function("1","2"))
fmt.Println(myThird_Function())
fmt.Println(myFourth_Function ())
}
希望对您有帮助。