为了账号安全,请及时绑定邮箱和手机立即绑定

在方法声明中允许可变数量的返回值

在方法声明中允许可变数量的返回值

Go
浮云间 2022-03-03 19:53:54
我有一个函数可以解决 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)}我明白那个[]接口{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)有什么建议吗?帮助?
查看完整描述

2 回答

?
HUX布斯

TA贡献1876条经验 获得超6个赞

请不要编写可怕的(并且由于无效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)

这种方法可能比后处理更健壮,但它排除了使用文字来构造值以在调用站点传递给您的函数,这不太“整洁”。


查看完整回答
反对 回复 2022-03-03
?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

最近我在玩 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 ())


}

我希望它对你有帮助。


https://play.golang.org/p/d6dSYLwbUB9


查看完整回答
反对 回复 2022-03-03
  • 2 回答
  • 0 关注
  • 146 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信