在Go语言中有函数重载的替代方法吗?

huangapple go评论121阅读模式
英文:

Alternative for function overloading in Go?

问题

在Golang中是否有可能像C#中的函数重载或可选参数一样工作?或者是否有其他替代方法?

英文:

Is it possible to work similar way like the function overloading or optional parameter in C# using Golang? Or maybe an alternative way?

答案1

得分: 13

在Go语言中,对于可选参数的惯用解决方案是使用包装函数:

  1. func do(a, b, c int) {
  2. // ...
  3. }
  4. func doSimply(a, b) {
  5. do(a, b, 42)
  6. }

故意不包含函数重载,因为它会使代码变得难以阅读。

英文:

The idiomatic answer to optional parameters in Go is wrapper functions:

  1. func do(a, b, c int) {
  2. // ...
  3. }
  4. func doSimply(a, b) {
  5. do(a, b, 42)
  6. }

Function overloading was intentionally left out, because it makes code hard(er) to read.

答案2

得分: 10

不支持函数重载和可选参数。您可以通过构建自己的参数结构来解决这个问题。我的意思是像这样(未经测试,可能不起作用...)编辑:现在已经测试过了...

  1. package main
  2. import "fmt"
  3. func main() {
  4. args := NewMyArgs("a", "b") // 默认情况下,文件名为"c"
  5. args.SetFileName("k")
  6. ret := Compresser(args)
  7. fmt.Println(ret)
  8. }
  9. func Compresser(args *MyArgs) string {
  10. return args.dstFilePath + args.srcFilePath + args.fileName
  11. }
  12. // 一个带有参数的结构体
  13. type MyArgs struct {
  14. dstFilePath, srcFilePath, fileName string
  15. }
  16. // 一个“构造函数”函数,为args提供默认值
  17. func NewMyArgs(dstFilePath string, srcFilePath string) *MyArgs {
  18. return &MyArgs{
  19. dstFilePath: dstFilePath,
  20. srcFilePath: srcFilePath,
  21. fileName: "c",
  22. }
  23. }
  24. func (a *MyArgs) SetFileName(value string) {
  25. a.fileName = value
  26. }
英文:

Neither function overloading nor optional arguments are directly supported. You could work around them building your own arguments struct. I mean like this (untested, may not work...) EDIT: now tested...

  1. package main
  2. import "fmt"
  3. func main() {
  4. args:=NewMyArgs("a","b") // filename is by default "c"
  5. args.SetFileName("k")
  6. ret := Compresser(args)
  7. fmt.Println(ret)
  8. }
  9. func Compresser(args *MyArgs) string {
  10. return args.dstFilePath + args.srcFilePath + args.fileName
  11. }
  12. // a struct with your arguments
  13. type MyArgs struct
  14. {
  15. dstFilePath, srcFilePath, fileName string
  16. }
  17. // a "constructor" func that gives default values to args
  18. func NewMyArgs(dstFilePath string, srcFilePath string) *MyArgs {
  19. return &MyArgs{
  20. dstFilePath: dstFilePath,
  21. srcFilePath:srcFilePath,
  22. fileName :"c"}
  23. }
  24. func (a *MyArgs) SetFileName(value string){
  25. a.fileName=value;
  26. }

答案3

得分: 3

有一些提示在这里使用可变参数,例如:

  1. sm1 := Sum(1, 2, 3, 4) // = 1 + 2 + 3 + 4 = 10
  2. sm2 := Sum(1, 2) // = 1 + 2 = 3
  3. sm3 := Sum(7, 1, -2, 0, 18) // = 7 + 1 + -2 + 0 + 18 = 24
  4. sm4 := Sum() // = 0
  5. func Sum(numbers ...int) int {
  6. n := 0
  7. for _,number := range numbers {
  8. n += number
  9. }
  10. return n
  11. }

或者对于任何类型使用...interface{}

  1. Ul("apple", 7.2, "BANANA", 5, "cHeRy")
  2. func Ul(things ...interface{}) {
  3. fmt.Println("<ul>")
  4. for _,it := range things {
  5. fmt.Printf(" <li>%v</li>\n", it)
  6. }
  7. fmt.Println("</ul>")
  8. }
英文:

There are some hints here using variadic arguments, for example:

  1. sm1 := Sum(1, 2, 3, 4) // = 1 + 2 + 3 + 4 = 10
  2. sm2 := Sum(1, 2) // = 1 + 2 = 3
  3. sm3 := Sum(7, 1, -2, 0, 18) // = 7 + 1 + -2 + 0 + 18 = 24
  4. sm4 := Sum() // = 0
  5. func Sum(numbers ...int) int {
  6. n := 0
  7. for _,number := range numbers {
  8. n += number
  9. }
  10. return n
  11. }

Or ...interface{} for any types:

  1. Ul(&quot;apple&quot;, 7.2, &quot;BANANA&quot;, 5, &quot;cHeRy&quot;)
  2. func Ul(things ...interface{}) {
  3. fmt.Println(&quot;&lt;ul&gt;&quot;)
  4. for _,it := range things {
  5. fmt.Printf(&quot; &lt;li&gt;%v&lt;/li&gt;\n&quot;, it)
  6. }
  7. fmt.Println(&quot;&lt;/ul&gt;&quot;)
  8. }

答案4

得分: 0

package main

import "fmt"

type flavorA struct{}
type flavorB struct{}

var FlavorA = flavorA{}
var FlavorB = flavorB{}

type Something struct {
i int
f float64
}

func (flavor flavorA) NewSomething(i int) *Something {
return &Something{i:i, f:0.0}
}

func (flavor flavorB) NewSomething(f float64) *Something {
return &Something{i:0, f:f}
}

func main() {
fmt.Println(FlavorA.NewSomething(1), FlavorB.NewSomething(2))
}

英文:

An approach I use sometime for constructing an object using New methods having different arguments is to have a "flavor" pseudo type. You can try it on the Go Playground https://play.golang.org/p/5To5AcY-MRe

  1. package main
  2. import &quot;fmt&quot;
  3. type flavorA struct{}
  4. type flavorB struct{}
  5. var FlavorA = flavorA{}
  6. var FlavorB = flavorB{}
  7. type Something struct {
  8. i int
  9. f float64
  10. }
  11. func (flavor flavorA) NewSomething(i int) *Something {
  12. return &amp;Something{i:i, f:0.0}
  13. }
  14. func (flavor flavorB) NewSomething(f float64) *Something {
  15. return &amp;Something{i:0, f:f}
  16. }
  17. func main() {
  18. fmt.Println(FlavorA.NewSomething(1), FlavorB.NewSomething(2))
  19. }

答案5

得分: 0

当你有很多参数时,使用一个新的结构体或定义一个新的MyOptionBuilder类型来构建和存储所有参数,并构造出漂亮的默认值可能是有意义的。

这里有一个简单的例子,其中Go的类型默认值是可以的。

  1. package main
  2. import "fmt"
  3. type FancyFuncOptions struct {
  4. I int64
  5. S string
  6. F float64
  7. //...更多...
  8. }
  9. func FancyFunc(opts *FancyFuncOptions) {
  10. fmt.Println("%v", opts)
  11. }
  12. func main() {
  13. // 简单的方式
  14. options := &FancyFuncOptions{S: "happy"}
  15. FancyFunc(options)

在Go中,如果选项具有复杂的逻辑,你会看到人们使用方法链。

  1. package main
  2. import "fmt"
  3. type FancyFuncOptions struct {
  4. I int64
  5. S string
  6. F float64
  7. //...更多...
  8. }
  9. // 链式风格
  10. func NewFancyFuncOptions() *FancyFuncOptions {
  11. return &FancyFuncOptions{I: 100, S: "empty", F: 0.1}
  12. }
  13. func (o *FancyFuncOptions) SetI(i int64) *FancyFuncOptions {
  14. o.I = i
  15. return o
  16. }
  17. func (o *FancyFuncOptions) SetS(s string) *FancyFuncOptions {
  18. o.S = s
  19. return o
  20. }
  21. func FancyFunc(opts *FancyFuncOptions) {
  22. fmt.Println("%v", opts)
  23. }
  24. func main() {
  25. // 更加复杂
  26. options = NewFancyFuncOptions().SetI(234).SetS("happy")
  27. FancyFunc(options)

(https://go.dev/play/p/Ae_6Y6kZa97)

明白了吗?

英文:

When you have many arguments it may make sense to use a new struct for them or to define a new MyOptionBuilder type to build and store all the arguments and to construct nice defaults.

Here's a simple example where the go defaults for types are okay.

  1. package main
  2. import &quot;fmt&quot;
  3. type FancyFuncOptions struct {
  4. I int64
  5. S string
  6. F float64
  7. //...many more...
  8. }
  9. func FancyFunc(opts *FancyFuncOptions) {
  10. fmt.Println(&quot;%v&quot;, opts)
  11. }
  12. func main() {
  13. // simple way
  14. options := &amp;FancyFuncOptions{S: &quot;happy&quot;}
  15. FancyFunc(options)

In golang you'll see people using method-chaining for this, if the options have complex logic.

  1. package main
  2. import &quot;fmt&quot;
  3. type FancyFuncOptions struct {
  4. I int64
  5. S string
  6. F float64
  7. //...many more...
  8. }
  9. // chaining style
  10. func NewFancyFuncOptions() *FancyFuncOptions {
  11. return &amp;FancyFuncOptions{I: 100, S: &quot;empty&quot;, F: 0.1}
  12. }
  13. func (o *FancyFuncOptions) SetI(i int64) *FancyFuncOptions {
  14. o.I = i
  15. return o
  16. }
  17. func (o *FancyFuncOptions) SetS(s string) *FancyFuncOptions {
  18. o.S = s
  19. return o
  20. }
  21. func FancyFunc(opts *FancyFuncOptions) {
  22. fmt.Println(&quot;%v&quot;, opts)
  23. }
  24. func main() {
  25. // fancier
  26. options = NewFancyFuncOptions().SetI(234).SetS(&quot;happy&quot;)
  27. FancyFunc(options)

(https://go.dev/play/p/Ae_6Y6kZa97)

Make sense?

huangapple
  • 本文由 发表于 2012年10月23日 18:33:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/13028486.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定