
离线 TA的专栏
- 打卡等级:热心大叔
- 打卡总天数:235
- 打卡月天数:1
- 打卡总奖励:3940
- 最近打卡:2025-12-16 12:01:17
|
目录
- 1.问题
- 2.使用反射实现
- 3.dablelv/cyan
- 4.小结
- 参考文献
1.问题
如何将一个切片连接成一个字符串呢?
您最先想到的可能是标准库 strings 包的 Join 函数。 - 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, ", "))
- }
复制代码运行输出: strings.Join 只能将字符串切片连接成字符串,但对于其他类型的切片呢?
事实上,标准库并没有针对每种类型的切片都给出一个实现,也没有使用反射给出一个通用的实现。既然没有那我们自己来实现一个吧。
2.使用反射实现
如果想要将任意类型的切片连接成字符串,可以使用反射(reflect)包来动态处理不同类型的切片,将元素转换为字符串,并连接成一个字符串。 - // 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 是将任意类型转为字符串。 - // 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()
- }
复制代码如果不关心错误,可以再封装一下。 - // 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, baz1, 2, 31.1, 2.2, 3.3true, false, truef, o, o
复制代码输出符合预期,我们通过反射,只用一个函数便可将任意类型的切片连接成字符串。
3.dablelv/cyan
以上代码已放到开源 Go 工具函数库 dablelv/cyan,可直接通过 go mod 方式进行 import 然后使用。
欢迎大家协同共建该工具函数库。 - 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.小结
对于字符串切片可以使用标准库 strings.Join 函数,对于其他任意类型的切片,利用 Golang 提供的反射能力,在运行时将切片元素转换为字符串并连接到一起。
参考文献
strings - Go Packages
github.com/dablelv/go-huge-util
到此这篇关于Golang切片连接成字符串的实现示例的文章就介绍到这了,更多相关Golang切片连接成字符串内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:  进行删除处理。
4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
|