我正在使用具有两个函数的第三方库,每个函数返回不同的类型.例如ArticleResponse和CommentResponse.
我想将调用其中任何一个函数的结果传递给我自己的函数.作为该函数的第二个参数,我想传递一个函数引用,该函数引用描述了如何将该响应打印到stdout.
response := GetArticles()
processResponse(response, printResponse)
func printResponse(response <what_type?>) {
for i := range response.Articles {
fmt.Println(response.Articles[i].Title)
}
}
Run Code Online (Sandbox Code Playgroud)
我不清楚如何强制或创建泛型类型,以便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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,更常见的样式是您的响应本身具有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()
}
Run Code Online (Sandbox Code Playgroud)
这种样式允许响应类型本身定义它们的打印行为,而processResponse函数只知道它有一些能够打印自己的类型.这也允许您向Response接口添加其他方法processResponse(或其他任何东西)以便与这些类型进行交互,而不必实际知道它被赋予了哪种类型.这使得您的代码基本上不那么脆弱,因为它不再依赖于每种响应类型的实际实现细节.它还允许您processReponse通过模拟Response接口来单独进行单元测试.