在Go中传递未知参数类型的函数引用
问题描述:
我正在使用第三方库,它有两个函数,每个函数返回不同的类型。例如。 ArticleResponse
和CommentResponse
。在Go中传递未知参数类型的函数引用
我想将这些函数的任何一个调用到我自己的函数中。作为该函数的第二个参数,我希望传递一个函数引用来描述如何将该响应输出到stdout。
response := GetArticles()
processResponse(response, printResponse)
func printResponse(response <what_type?>) {
for i := range response.Articles {
fmt.Println(response.Articles[i].Title)
}
}
这不是我清楚如何强迫或创建泛型类型,以便printResponse函数知道要期待它的参数传递什么。
如果我没有提供足够好的描述,我想在这里做什么,请让我知道,我会编辑/更新问题。
答
你仅在这种情况下实际选项对于processResponse
接受接受相同的interface{}
和一个函数,然后printResponse
接受相同的空接口,并键入断言它(或使用类型的开关)。例如:
func main() {
response := GetArticles()
processResponse(response, printResponse)
}
func processResponse(response interface{}, printResponse func(interface{}))
{
// Process
printResponse(response)
}
func printResponse(response interface{}) {
switch r = reponse.(type) {
case ArticleResponse:
for i := range r.Articles {
fmt.Println(r.Articles[i].Title)
}
case CommentResponse:
for i := range r.Comments {
fmt.Println(r.Comments[i].Topic, r.Comments[i].User)
}
}
}
然而,更常见的风格将是你的反应本身有一个Print方法(或类似),并为您的处理功能,接受表示常用方法的接口。例如:
type ArticleReponse struct {
// ...
}
func (a ArticleReponse) Print() {
for i := range a.Articles {
fmt.Println(a.Articles[i].Title)
}
}
type CommentResponse struct {
// ...
}
func (c CommentResponse) Print() {
for i := range c.Comments {
fmt.Println(c.Comments[i].Topic, c.Comment[i].User)
}
}
type Response interface {
Print()
}
func main() {
response := GetArticles()
processResponse(response)
}
func processResponse(response Response)
{
// Process
response.Print()
}
这种风格使得响应类型本身来定义他们的印刷行为,而processResponse
功能只知道它有一些类型这是能够打印本身。这也允许你添加其他方法到processResponse
(或其他任何)可能需要的响应接口,以便与这些类型进行交互,而不必知道它给出了哪种类型。这使得你的代码不再脆弱,因为它不再依赖于每种响应类型的实际实现细节。它还允许您通过嘲笑Response
接口来隔离单元测试processReponse
。
答
您可以创建一个Content
& ContentList
接口
type Content interface {
GetTitle() string
}
type ContentList interface {
Contents() []Content
}
func printResponse(response ContentList) {
for content := range response.Contents() {
fmt.Println(content.GetTitle())
}
}
然后ArticleResponse
& CommentResponse
应该实现ContentList
接口和Aticle
& Comment
应该实现Content
接口。
如果你只处理两种类型,甚至更多一点,你也可以做这样的事情https://play.golang.org/p/cVtlTu61b5 – mkopriva