在Go中传递未知参数类型的函数引用

问题描述:

我正在使用第三方库,它有两个函数,每个函数返回不同的类型。例如。 ArticleResponseCommentResponse在Go中传递未知参数类型的函数引用

我想将这些函数的任何一个调用到我自己的函数中。作为该函数的第二个参数,我希望传递一个函数引用来描述如何将该响应输出到stdout。

response := GetArticles() 
processResponse(response, printResponse) 

func printResponse(response <what_type?>) { 
    for i := range response.Articles { 
     fmt.Println(response.Articles[i].Title) 
    } 
} 

这不是我清楚如何强迫或创建泛型类型,以便printResponse函数知道要期待它的参数传递什么。

如果我没有提供足够好的描述,我想在这里做什么,请让我知道,我会编辑/更新问题。

+0

如果你只处理两种类型,甚至更多一点,你也可以做这样的事情https://play.golang.org/p/cVtlTu61b5 – mkopriva

你仅在这种情况下实际选项对于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接口。