将[] fmt.Stringer参数传递给函数

时间:2019-06-20 14:11:58

标签: go

我有一个实现了Stringer接口的类型

// RowID stores the ID of a single row in a table
type RowID []string

// String implements Stringer interface for RowID
func (r RowID) String() string {
    return fmt.Sprintf("[%s]", strings.Join(r, ", "))
}

我有一个函数想要将此类型的切片(或实现Stringer接口的任何其他类型)传递给该函数。

// PrintChanges ...
func PrintChanges(ids []fmt.Stringer) {
    for _, id := range ids {
        fmt.Println(id)
    }
}

但是,go编译器给我一个错误:

cannot use rowIDs (type []RowID) as type []fmt.Stringer in argument to PrintChanges

我可以将RowID传递给接受单个fmt.Stringer的函数

func PrintChange(id fmt.Stringer) {
    fmt.Println(id)
}

...
    PrintChange(RowID{"1", "24"})

但是由于某种原因,我无法将RowID的切片传递给接受fmt.Stringer切片的函数。我想念什么?

Go Playground

1 个答案:

答案 0 :(得分:1)

保持简单

专业的Go程序员认为可以对每种类型重复这样的功能,或者对要打印的每个切片都进行for循环是可以的。这是因为Go的目标是尽可能地易于阅读,也就是说,第一次阅读一段代码的人不应问“该函数调用将转到哪个函数重载”之类的问题(C ++中的常见陷阱, Go没有函数重载)。因此,您可以只写main()

游乐场:https://ideone.com/IL3rGR

    for _, id := range rowIDs { fmt.Println(id) }

简洁明了。

请注意,fmt.Println(id)不会调用您的String()函数

这是因为fmt库使用reflect库并对string类型的硬编码行为进行了尝试,您尝试将其替换。 RowID实例也是string实例,该库始终比其类型别名更喜欢string。我会说这是库中的错误:

库来源:https://golang.org/src/fmt/print.go#L649

    // Some types can be done without reflection.
    switch f := arg.(type) {
...
    case string:
        p.fmtString(f, verb)

如果您真的想

您可以使用带有接口{}的函数,并使运行时反映类型转换为Stringer切片的类型。请注意,这意味着您仅在运行时不会在编译期间看到类型不匹配:

游乐场:https://ideone.com/vlrBP9

func castToStringerSlice(iface interface{}) ([]fmt.Stringer, bool /* ok */) {
    if reflect.TypeOf(iface).Kind() != reflect.Slice {
        return nil, false
    }

    v := reflect.ValueOf(iface)
    stringers := make([]fmt.Stringer, v.Len())

    for i := 0; i < v.Len(); i++ {
        stringers[i] = v.Index(i)
    }

    return stringers, true
}

func PrintChanges(iface_ids interface{}) {
    ids, ok := castToStringerSlice(iface_ids)
    if !ok {
        log.Fatal(errors.New("the argument to PrintChanges must be a slice of Stringers"))
    }
    for _, id := range ids {
        fmt.Println(id)
    }
}

资源: