在 Go 中,将字符串类型数组转换为字符串数组的最佳方法是什么

In Go what is the best way to convert an array of string types to an array of string

以下代码

package main

import "strings"
import "fmt"

type Foo string

const (
    Bar    Foo = "bar"
    Snafu      = "snafu"
    Foobar     = "foobar"
)

var Foos = []Foo{Bar, Snafu, Foobar}

func main() {
    fmt.Println("Foos: " + strings.Join(Foos, ","))
}

产生此错误:

./test.go:17: cannot use Foos (type []Foo) as type []string in argument to strings.Join

这是有道理的,因为 Foo 不是字符串,而是派生自字符串。有没有办法在不复制的情况下将“[]Foo”强制转换为“[]string”?

几乎最好也是唯一的方法是遍历 Foo 对象的切片,如(导致复制):

func main() {
    results := make([]string, 0, len(Foos))
    for _, r := range Foos{
       results = append(results, string(r))
    }
    fmt.Println("Foos: " + strings.Join(results, ","))
}

不幸的是,此时 Go 不支持概念类型强制转换,需要一个副本。作为替代方案,您可以键入 alias []Foo 并向其添加 Stringer 方法,从而封装此类详细信息,例如:http://play.golang.org/p/FuOoLNrCvD

类似问题请看下面:Cannot convert []string to []interface {}

您可以使用我创建的 https://github.com/ledongthuc/goterators#map 来重用聚合和转换函数。

package main

import (
    "fmt"
    "strings"

    "github.com/ledongthuc/goterators"
)

type Foo string

const (
    Bar    Foo = "bar"
    Snafu      = "snafu"
    Foobar     = "foobar"
)

var Foos = []Foo{Bar, Snafu, Foobar}

func main() {
    strs := goterators.Map(Foos, func(item Foo) string {
        return string(item)
    })
    fmt.Println("Foos: " + strings.Join(strs, ","))
}

或者如果你想要一个优化的方式,你可以使用 Reduce

package main

import (
    "fmt"

    "github.com/ledongthuc/goterators"
)

type Foo string

const (
    Bar    Foo = "bar"
    Snafu      = "snafu"
    Foobar     = "foobar"
)

var Foos = []Foo{Bar, Snafu, Foobar}

func main() {
    joinStr := goterators.Reduce(Foos, "", func(previous string, current Foo, index int, list []Foo) string {
        if len(previous) == 0 {
            return string(current)
        }
        return previous + "," + string(current)
    })
    fmt.Println("Foos: " + joinStr)
}

它们需要 1.18 才能使用,支持通用 + 动态类型。