我正在使用具有两个函数的第三方库,每个函数都返回不同的类型。例如。 ArticleResponse
和CommentResponse
。
我想将调用其中任何一个函数的结果传递给我自己的函数。作为该函数的第二个参数,我想传递一个函数引用,该函数引用描述如何将该响应打印到stdout。
response := GetArticles()
processResponse(response, printResponse)
func printResponse(response <what_type?>) {
for i := range response.Articles {
fmt.Println(response.Articles[i].Title)
}
}
我不清楚如何强制或创建泛型类型,以便printResponse函数知道期望在其参数中传递什么。
如果我没有提供足够好的描述我在这里尝试做什么,请告诉我,我会编辑/更新问题。
答案 0 :(得分:7)
在这种情况下,您唯一真正的选择是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
(或其他任何)可能需要的响应接口,以便与这些类型进行交互,而无需实际知道它被赋予了哪种类型。这使得您的代码基本上不那么脆弱,因为它不再依赖于每种响应类型的实际实现细节。它还允许您通过模拟processReponse
接口来单独测试Response
。
答案 1 :(得分:0)
您可以创建Content
&amp; 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
&amp; CommentResponse
应实施ContentList
界面和Aticle
&amp; Comment
应该实现Content
接口。