2015-12-22 70 views
2

我想要去一个小项目,并试图写这些功能:我该如何编写一个可以使用多种类型的函数呢?

func fatal(reason string) { 
    println(reason) 
    os.Exit(1) 
} 

func fatal(err error) { 
    fatal(err.Error()) 
} 

挖约了一下,发现this answer,其中引用the docs on overloading,我意识到,我试图做的是在旅途中违法后。

我想要的是一个简单的api,它允许我调用致命的字符串或错误来简化我的逻辑。我如何实现这一目标或类似的目标?

如果func fatal(reason string)func fatalErr(err error)一起出现,会不会觉得不合适?我是否错过了该语言的另一个特点,可以让我做我想做的事情?

回答

3

执行此操作的最常见方法是将方法定义为func fatal(err interface{}),然后键入断言或在其正文中使用类型开关来处理每种不同类型。如果我为你的例子编码,它会看起来像这样;

func fatal(err interface{}) { 
    if v, ok := err.(string); ok { 
     fmt.Println(v) 
    } 
    if v, ok := err.(error); ok { 
      fmt.Println(v.Error()) 
    } else { 
     // panic ? 
    } 
} 

另外;这里有一个关于类型开关和断言的快速阅读,可能会有所帮助; http://blog.denevell.org/golang-interface-type-assertions-switch.html 您还可以查看effective-go,因为它包含两个功能部分。

+0

类型切换和类型断言。谢谢,这看起来正是我想要的谷歌。 :)。看起来很遗憾我们需要通过将其转换为空白界面来丢失类型信息。有什么方法可以创建一个字符串或错误的类型,并说我们的致命函数使用某种类型的东西? –

+0

@ MikeH-R你可以声明一个接口,它既是字符串又是err实现的。你的用例有点奇怪。 'error'实际上是一个接口,它的唯一方法是'Error()',它返回你想要显示的字符串作为错误。这里有另一个想法......做一个只接受'error'的致命的单一定义,然后当你有一个字符串并将错误传递给它时,执行'errors.New(theString)'。如果您好奇,这里是错误包源代码; https://golang.org/src/errors/errors.go – evanmcdonnal

+0

谢谢埃文,非常有帮助。 –

1

该语言不支持函数重载。它从官方Golang网站上说,

如果方法调度不需要进行类型匹配,它也被简化了。使用其他语言的经验告诉我们,使用同一名称但签名不同的多种方法偶尔有用,但在实践中也可能会令人困惑和脆弱。 Go只有通过名称匹配并要求类型一致才是Go类型系统的一个重要简化决策。 关于运算符重载,它似乎比绝对要求更方便。再说一遍,没有它就更简单了。

https://golang.org/doc/faq#overloading

一个潜在的解决方案将是定义该类型的检查和对你如何重载多种功能类似处理不同类型的高级功能。查看@ evanmcdonnal的解决方案就是一个很好的例子。

+0

我链接到我的问题。 :) –

+0

你也没有提供任何形式的答案,只是事实陈述。试着将这个想法扩展到你如何在Go中处理这个问题,而不仅仅是说明你不能重载方法。 – evanmcdonnal

+1

@evanmcdonnal我正在给出一个关于你有什么样的例子的高层次解释。在电话上打字并不是最有效的回答方式。 +1给你的答案。 –

2

改为使用log.Fatal()。 https://golang.org/pkg/log/#Fatal

您可以使用interface {},但不推荐使用它,因为当您这样做时会失去所有类型检查的好处。 Go作者可以使用interface {},因为他们理解使用interface时需要执行的其他测试和检查的适当级别。当需要类似的东西时,使用内建和标准库函数更容易(即使是中级和高级地鼠)。

Go不具有代数或/和类型。标准的解决方法是用指针定义一个和/产品类型(例如struct {* string,* error}),并努力确保在任何时间点只让其中一个字段不为零。

+0

嗨,谢谢@voutasaurus。我只是从使用'log.Fatal'到其他东西,它_almosts_完全是我想要的,但我被它打印的时间戳所困扰,所以写了(或试图写)一个类似的帮助函数。 (编写一个小命令行应用程序,时间戳感觉没有必要)。感谢提示和OR类型的信息。 (然后再一次,你永远无法像其他地方的Haskell一样获得类型系统,感叹)。 –

+2

你可以定义你自己的记录器,它不会在一行中打印时间戳:http://play.golang.org/p/TLMxtCag_0 – voutasaurus

+1

哈哈哈,你是对的!首先让我阅读日志软件包,这对我来说是正确的。哦,至少我学到了一些东西。 –

相关问题