Golang切片連接成字符串的實現(xiàn)示例
1.問題
如何將一個切片連接成一個字符串呢?
您最先想到的可能是標(biāo)準(zhǔn)庫 strings 包的 Join 函數(shù)。
func Join(elems []string, sep string) string
Join 將字符串切片的所有元素連接成一個字符串,各個元素間使用給定的字符串分隔。
package main import ( "fmt" "strings" ) func main() { s := []string{"foo", "bar", "baz"} fmt.Println(strings.Join(s, ", ")) }
運行輸出:
foo, bar, baz
strings.Join 只能將字符串切片連接成字符串,但對于其他類型的切片呢?
事實上,標(biāo)準(zhǔn)庫并沒有針對每種類型的切片都給出一個實現(xiàn),也沒有使用反射給出一個通用的實現(xiàn)。既然沒有那我們自己來實現(xiàn)一個吧。
2.使用反射實現(xiàn)
如果想要將任意類型的切片連接成字符串,可以使用反射(reflect)包來動態(tài)處理不同類型的切片,將元素轉(zhuǎn)換為字符串,并連接成一個字符串。
// JoinE concatenates all elements of Array, Slice or String to a single string with a separator // and returns an error if an error occurred. // E.g. input []int{1, 2, 3} and separator ",", output is a string "1,2,3". // It panics if a's Kind is not Array, Slice, or String. func JoinE(a any, sep string) (string, error) { v := reflect.ValueOf(a) if v.Kind() == reflect.String { return JoinE(strings.Split(a.(string), ""), sep) } var s string for i := 0; i < v.Len(); i++ { if len(s) > 0 { s += sep } str, err := conv.ToStringE(v.Index(i).Interface()) if err != nil { return "", err } s += str } return s, nil }
其中 ToStringE 是將任意類型轉(zhuǎn)為字符串。
// ToStringE casts any type to a string type. func ToStringE(i any) (string, error) { i = indirectToStringerOrError(i) switch s := i.(type) { case string: return s, nil case bool: return strconv.FormatBool(s), nil case int: return strconv.Itoa(s), nil case int64: return strconv.FormatInt(s, 10), nil case int32: return strconv.Itoa(int(s)), nil case int16: return strconv.FormatInt(int64(s), 10), nil case int8: return strconv.FormatInt(int64(s), 10), nil case uint: return strconv.FormatUint(uint64(s), 10), nil case uint64: return strconv.FormatUint(uint64(s), 10), nil case uint32: return strconv.FormatUint(uint64(s), 10), nil case uint16: return strconv.FormatUint(uint64(s), 10), nil case uint8: return strconv.FormatUint(uint64(s), 10), nil case float64: return strconv.FormatFloat(s, 'f', -1, 64), nil case float32: return strconv.FormatFloat(float64(s), 'f', -1, 32), nil case json.Number: return s.String(), nil case []byte: return string(s), nil case template.HTML: return string(s), nil case template.HTMLAttr: return string(s), nil case template.URL: return string(s), nil case template.JS: return string(s), nil case template.JSStr: return string(s), nil case template.CSS: return string(s), nil case template.Srcset: return string(s), nil case nil: return "", nil case fmt.Stringer: return s.String(), nil case error: return s.Error(), nil default: return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i) } } // Copied from html/template/content.go. // indirectToStringerOrError returns the value, after dereferencing as many times // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer // or error. func indirectToStringerOrError(a any) any { if a == nil { return nil } v := reflect.ValueOf(a) for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Pointer && !v.IsNil() { v = v.Elem() } return v.Interface() }
如果不關(guān)心錯誤,可以再封裝一下。
// Join concatenates all elements of Array, Slice or String to a single string with a separator. func Join(a any, sep string) string { s, _ := JoinE(a, sep) return s }
我們使用不同類型的切片來驗證一下。
package main import ( "fmt" "strings" ) func main() { s := []string{"foo", "bar", "baz"} fmt.Println(Join(s, ", ")) i := []int{1, 2, 3} fmt.Println(Join(i, ", ")) f := []float64{1.1, 2.2, 3.3} fmt.Println(Join(f, ", ")) b := []bool{true, false, true} fmt.Println(Join(b, ", ")) // 可以將字符串看成字符切片。 str := "foo" fmt.Println(Join(str, ", ")) }
運行輸出:
foo, bar, baz
1, 2, 3
1.1, 2.2, 3.3
true, false, true
f, o, o
輸出符合預(yù)期,我們通過反射,只用一個函數(shù)便可將任意類型的切片連接成字符串。
3.dablelv/cyan
以上代碼已放到開源 Go 工具函數(shù)庫 dablelv/cyan,可直接通過 go mod 方式進行 import 然后使用。
歡迎大家協(xié)同共建該工具函數(shù)庫。
import ( "github.com/dablelv/cyan/str" ) str.Join([]string{"foo", "bar", "baz"}, ", ") str.Join([]int{1, 2, 3}, ", ") str.Join([]float64{1.1, 2.2, 3.3}, ", ") str.Join([]bool{true, false, true}, ", ") str.Join("foo", ", ")
4.小結(jié)
對于字符串切片可以使用標(biāo)準(zhǔn)庫 strings.Join 函數(shù),對于其他任意類型的切片,利用 Golang 提供的反射能力,在運行時將切片元素轉(zhuǎn)換為字符串并連接到一起。
參考文獻
github.com/dablelv/go-huge-util
到此這篇關(guān)于Golang切片連接成字符串的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)Golang切片連接成字符串內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
GOLANG使用Context管理關(guān)聯(lián)goroutine的方法
這篇文章主要介紹了GOLANG使用Context管理關(guān)聯(lián)goroutine的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01