设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间01 现在时间01 缓存数据 当你走完一段之后回头看,你会发现,那些真正能被记得的事真的是没有多少,真正无法忘记的人屈指可数,真正有趣的日子不过是那么一些,而真正需要害怕的也是寥寥无几。

当你走完一段之后回头看,你会发现,那些真正能被记得的事真的是没有多少,真正无法忘记的人屈指可数,真正有趣的日子不过是那么一些,而真正需要害怕的也是寥寥无几。

查看: 879|回复: 2

Golang切片连接成字符串的实现示例

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:235
  • 打卡月天数:1
  • 打卡总奖励:3940
  • 最近打卡:2025-12-16 12:01:17
等级头衔

等級:晓枫资讯-上等兵

在线时间
4 小时

积分成就
威望
0
贡献
462
主题
410
精华
0
金钱
5289
积分
945
注册时间
2023-1-6
最后登录
2025-12-16

发表于 2024-5-22 04:13:37 来自手机 | 显示全部楼层 |阅读模式
目录


  • 1.问题
  • 2.使用反射实现
  • 3.dablelv/cyan
  • 4.小结
  • 参考文献

1.问题

如何将一个切片连接成一个字符串呢?
您最先想到的可能是标准库 strings 包的 Join 函数。
  1. func Join(elems []string, sep string) string
复制代码
Join 将字符串切片的所有元素连接成一个字符串,各个元素间使用给定的字符串分隔。
  1. package main

  2. import (
  3.         "fmt"
  4.         "strings"
  5. )

  6. func main() {
  7.         s := []string{"foo", "bar", "baz"}
  8.         fmt.Println(strings.Join(s, ", "))
  9. }
复制代码
运行输出:
  1. foo, bar, baz
复制代码
strings.Join 只能将字符串切片连接成字符串,但对于其他类型的切片呢?
事实上,标准库并没有针对每种类型的切片都给出一个实现,也没有使用反射给出一个通用的实现。既然没有那我们自己来实现一个吧。

2.使用反射实现

如果想要将任意类型的切片连接成字符串,可以使用反射(reflect)包来动态处理不同类型的切片,将元素转换为字符串,并连接成一个字符串。
  1. // JoinE concatenates all elements of Array, Slice or String to a single string with a separator
  2. // and returns an error if an error occurred.
  3. // E.g. input []int{1, 2, 3} and separator ",", output is a string "1,2,3".
  4. // It panics if a's Kind is not Array, Slice, or String.
  5. func JoinE(a any, sep string) (string, error) {
  6.         v := reflect.ValueOf(a)
  7.         if v.Kind() == reflect.String {
  8.                 return JoinE(strings.Split(a.(string), ""), sep)
  9.         }
  10.         var s string
  11.         for i := 0; i < v.Len(); i++ {
  12.                 if len(s) > 0 {
  13.                         s += sep
  14.                 }
  15.                 str, err := conv.ToStringE(v.Index(i).Interface())
  16.                 if err != nil {
  17.                         return "", err
  18.                 }
  19.                 s += str
  20.         }
  21.         return s, nil
  22. }
复制代码
其中 ToStringE 是将任意类型转为字符串。
  1. // ToStringE casts any type to a string type.
  2. func ToStringE(i any) (string, error) {
  3.         i = indirectToStringerOrError(i)

  4.         switch s := i.(type) {
  5.         case string:
  6.                 return s, nil
  7.         case bool:
  8.                 return strconv.FormatBool(s), nil
  9.         case int:
  10.                 return strconv.Itoa(s), nil
  11.         case int64:
  12.                 return strconv.FormatInt(s, 10), nil
  13.         case int32:
  14.                 return strconv.Itoa(int(s)), nil
  15.         case int16:
  16.                 return strconv.FormatInt(int64(s), 10), nil
  17.         case int8:
  18.                 return strconv.FormatInt(int64(s), 10), nil
  19.         case uint:
  20.                 return strconv.FormatUint(uint64(s), 10), nil
  21.         case uint64:
  22.                 return strconv.FormatUint(uint64(s), 10), nil
  23.         case uint32:
  24.                 return strconv.FormatUint(uint64(s), 10), nil
  25.         case uint16:
  26.                 return strconv.FormatUint(uint64(s), 10), nil
  27.         case uint8:
  28.                 return strconv.FormatUint(uint64(s), 10), nil
  29.         case float64:
  30.                 return strconv.FormatFloat(s, 'f', -1, 64), nil
  31.         case float32:
  32.                 return strconv.FormatFloat(float64(s), 'f', -1, 32), nil
  33.         case json.Number:
  34.                 return s.String(), nil
  35.         case []byte:
  36.                 return string(s), nil
  37.         case template.HTML:
  38.                 return string(s), nil
  39.         case template.HTMLAttr:
  40.                 return string(s), nil
  41.         case template.URL:
  42.                 return string(s), nil
  43.         case template.JS:
  44.                 return string(s), nil
  45.         case template.JSStr:
  46.                 return string(s), nil
  47.         case template.CSS:
  48.                 return string(s), nil
  49.         case template.Srcset:
  50.                 return string(s), nil
  51.         case nil:
  52.                 return "", nil
  53.         case fmt.Stringer:
  54.                 return s.String(), nil
  55.         case error:
  56.                 return s.Error(), nil
  57.         default:
  58.                 return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i)
  59.         }
  60. }

  61. // Copied from html/template/content.go.
  62. // indirectToStringerOrError returns the value, after dereferencing as many times
  63. // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
  64. // or error.
  65. func indirectToStringerOrError(a any) any {
  66.         if a == nil {
  67.                 return nil
  68.         }
  69.         v := reflect.ValueOf(a)
  70.         for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Pointer && !v.IsNil() {
  71.                 v = v.Elem()
  72.         }
  73.         return v.Interface()
  74. }
复制代码
如果不关心错误,可以再封装一下。
  1. // Join concatenates all elements of Array, Slice or String to a single string with a separator.
  2. func Join(a any, sep string) string {
  3.         s, _ := JoinE(a, sep)
  4.         return s
  5. }
复制代码
我们使用不同类型的切片来验证一下。
  1. package main

  2. import (
  3.         "fmt"
  4.         "strings"
  5. )

  6. func main() {
  7.         s := []string{"foo", "bar", "baz"}
  8.         fmt.Println(Join(s, ", "))
  9.        
  10.         i := []int{1, 2, 3}
  11.         fmt.Println(Join(i, ", "))

  12.         f := []float64{1.1, 2.2, 3.3}
  13.         fmt.Println(Join(f, ", "))
  14.        
  15.         b := []bool{true, false, true}
  16.         fmt.Println(Join(b, ", "))

  17.         // 可以将字符串看成字符切片。
  18.         str := "foo"
  19.         fmt.Println(Join(str, ", "))
  20. }
复制代码
运行输出:
  1. foo, bar, baz1, 2, 31.1, 2.2, 3.3true, false, truef, o, o
复制代码
输出符合预期,我们通过反射,只用一个函数便可将任意类型的切片连接成字符串。

3.dablelv/cyan

以上代码已放到开源 Go 工具函数库 dablelv/cyan,可直接通过 go mod 方式进行 import 然后使用。
欢迎大家协同共建该工具函数库。
  1. import (
  2.         "github.com/dablelv/cyan/str"
  3. )

  4. str.Join([]string{"foo", "bar", "baz"}, ", ")
  5. str.Join([]int{1, 2, 3}, ", ")
  6. str.Join([]float64{1.1, 2.2, 3.3}, ", ")
  7. str.Join([]bool{true, false, true}, ", ")
  8. str.Join("foo", ", ")
复制代码
4.小结

对于字符串切片可以使用标准库 strings.Join 函数,对于其他任意类型的切片,利用 Golang 提供的反射能力,在运行时将切片元素转换为字符串并连接到一起。

参考文献

strings - Go Packages
github.com/dablelv/go-huge-util
到此这篇关于Golang切片连接成字符串的实现示例的文章就介绍到这了,更多相关Golang切片连接成字符串内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
16
积分
12
注册时间
2022-12-29
最后登录
2022-12-29

发表于 2024-11-3 21:44:29 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
19
积分
18
注册时间
2022-12-25
最后登录
2022-12-25

发表于 4 天前 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表