GO中字符串操作和转换简介

Posted 黄河大道东

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GO中字符串操作和转换简介相关的知识,希望对你有一定的参考价值。

go中字符串是一种基本类型(string),是一个不可改变的UTF-8字符序列:

  • 一个ASCII码占用1个字节(8位);
  • 其它字符根据需要占用2-4个字节;

字符串

字符串创建后,就不可修改;

声明与初始化

go支持两种类型的字符串字面量:

  • 解释型字符串:双引号括起来的字符串(“”),转义字符(如\\n\\r等)会被替换掉;
var s string
s := "hello"
  • 非解释型字符串:用反引号(键盘左上角上的)括起来的字符串,转义字符不会被解释且可跨行(原样输出);
s := `hello
 world!
 line2`
fmt.Println(s)

长度

  • len()返回字符串中的字节数(非字符数目)
  • 索引操作s[i]返回字符串s中第i个字节的值(非Ascii码返回对应字节的数值)
  • 要获取对应字符数(包含非ASCII字符时)需要使用utf8.RuneCountInString

比较

  • ==:直接比较,区分大小写(效率最高);
  • strings.Compare(a,b):返回值为 int, 0 表示两数相等,1 表示 a>b, -1 表示 a<b。区分大小写;
  • strings.EqualFold(a,b):直接返回是否相等,不区分大小写。

拼接

  • 加号(+):最常用、方便的,但每次拼接都会生成一个新的字符串,效率较低;
  • fmt.Sprintf():通过格式化字符串方式拼接;
  • strings.Join():可以指定拼接时的间隔符;
  • bytes.Buffer:可变大小的字节缓冲区,提供方便地读写操作;
  • strings.Builder:通过write方法高效地构造字符串,最小化内存拷贝;

一般简单拼接直接使用+,字符串数组/切片拼接为字符串时用Join,多条不相关字符串拼接时用Builder。

var buff bytes.Buffer
buff.WriteString("hello")
buff.WriteRune(\'字\')
buff.WriteString("符")
fmt.Println(buff.String()) // hello字符

var build strings.Builder
build.WriteString("hello")
build.WriteRune(\'字\')
build.WriteString("符")
fmt.Println(build.String()) // hello字符

截取

go中可通过切片方式快速获截取s=src[low:high](指定索引范围,‘左含右不含’)。索引不能越界,否则会导致panic异常。

s := "abcdef"
fmt.Println(s[1:4],s[1:],s[:1]) // bcd bcdef a

对于包含中文的字符串,需要转换为rune后操作(否则会出现乱码):

  • 字符串转换为rune切片:
  • 切片截取;
  • 截取结果转换回string;
name := "test中文字符串测试"
runeName := []rune(name)
log.Printf("str-len(输出字节数): %v, rune-len(输出字符数): %v", len(name), len(runeName))
for i := 2; i <= len(runeName); i++ 
	log.Printf("len-%v: %v", i, string(runeName[:i]))

遍历

有两种遍历方式:下标与range

  • 下标遍历:输出的是每个字节
  • range遍历:输出对应的Unicode字符
s1 := "W字符"
// 输出7个数值(每个字节对应数值)
for i:=0; i<len(s1); i++
	fmt.Println(s1[i])


// 输出三个字符(分别:W 字 符)
for i, v:=range s1
	fmt.Println(i, string(v))

修改

go中字符串内容默认不能修改,若要修改需要转换为[]byte[]rune类型修改后再转回:

s := "W字符"
b := []byte(s)
fmt.Println(len(b)) // 7
b[0] = \'M\'  // Ascii码字符,或0-255之间的数
fmt.Println(string(b)) // M字符

r := []rune(s)
fmt.Println(len(r)) // 3
r[1] = \'世\' // Unicode字符,或者对应的数字表示
fmt.Println(string(r)) // W世符

strings包

strings中包含了一些常用的字符串操作函数,在涉及到字符串修改时,返回新的串。

  • 前后缀:HasPrefix、HasSuffix;
  • 是否包含:Contains;
  • 大小写转换:ToLower、ToUpper、Title;
  • 修剪:Trim、Trimleft、TrimRight;TrimSpace去除空白
  • 拼接拆分:Join、Split、Fields(根据空白分割);
  • 查找位置(-1表示表示未找到):Index、LastIndex、IndexRune;
  • 统计数量:Count;
  • 重叠串:Repeat,重复n次生成新的串;
  • 替换:Replace,可指定替换数量,负数表示全部替换;

Map

func Map(mapping func(rune) rune, s string) string,根据mapping函数修改s中的字符,并返回修改后新的串;若mapping返回负值,则删除对应字符。

m := func(r rune) rune 
	switch 
	case r >= \'A\' && r <= \'Z\':
		return \'A\' + (r-\'A\'+13)%26
	case r >= \'a\' && r <= \'z\':
		return \'a\' + (r-\'a\'+13)%26
	
	return r

fmt.Println(strings.Map(m, "Twas brillig and the slithy gopher..."))

Reader

用于读取字符串,实现了io.Reader、io.ReaderAt、io.Seeker、io.WriterTo、io.ByteScanner、io.RuneScanner。

r := strings.NewReader("abcdefghijklmn")
fmt.Println("total len:", r.Len())   // 14
var buf []byte
buf = make([]byte, 5)
readLen, err := r.Read(buf)
fmt.Println("read len:", readLen) // 5
if err != nil 
	fmt.Println("error:", err)

fmt.Println(string(buf))            // abcde
fmt.Println("remain len:", r.Len())	// 9   读取到了5个 剩余未读是14-5
fmt.Println("size:", r.Size()) 		// 14   字符串的长度

Replacer

用于字符串替换;Replacer中包含要替换字符串的列表,且是线程安全的:

r := strings.NewReplacer("<", "&lt;", ">", "&gt;")
fmt.Println(r.Replace("This is <b>HTML</b>!")) // This is &lt;b&gt;HTML&lt;/b&gt;!

strconv包

strconv包用于字符串与其它类型间的转换:

  • 整数转字符串:strconv.FormatInt、strconv.FormatUint、strconv.Itoa(相当于FormatInt(i, 10));

  • 布尔转字符串(“true” 或 “false”):strconv.FormatBool;

  • 浮点转字符串:strconv.FormatFloat;

  • 字符串转整数:strconv.ParseInt、strconv.ParseUint、strconv.Atoi(相当于ParseInt(s, 10, 0));

  • 字符串转布尔:strconv.ParseBool(1,t,T,TRUE,true,True为真;0,f,F,FALSE,false,False为假);

  • 字符串转浮点:strconv.ParseFloat;

  • appendXXX:在[]byte后追加对应类型;

在转换时,会出现两种类型的错误:

  • ErrRange:表示值超过了类型能表示的最大范围。
  • ErrSyntax:表示语法错误。

字符串转整数

func ParseInt(s string, base int, bitSize int)(i int64, err error)

  • s:要转换的字符串
  • base:进位制(2~36 进制),0根据字符串判断进制(0x:16,0:8,其它:10)
  • bitSize:指定整数类型(0:int、8:int8、16:int16、32:int32、64:int64)

常用的Atoi,是一个简易版,相当于ParseInt(s, 10, 0)

浮点数转字符串

func FormatFloat(f float64, fmt byte, prec, bitSize int) string

f:要转换的浮点数

  • fmt:格式标记(b、e、E、f、g、G)
  • prec:精度(数字部分的长度,不包括指数部分)
  • bitSize:指定浮点类型(32:float32、64:float64)

FormatFloat参数只接收64位浮点,要转换32位浮点可:

  • 使用fmt.Sprintf实现;
  • 使用FormatFloat:需转为float64,但bitSize使用32;
var v32 float32 = 3.1415926535
var v64 float64 = 3.1415926535
s32 := fmt.Sprintf("%.4f", v32)
s32_1 := strconv.FormatFloat(float64(v32), \'f\', 4, 32)
s64 := strconv.FormatFloat(v64, \'f\', 4, 64)

格式标记:

  • ‘b’ (-ddddp±ddd,二进制指数)
  • ‘e’ (-d.dddde±dd,十进制指数)
  • ‘E’ (-d.ddddE±dd,十进制指数)
  • ‘f’ (-ddd.dddd,没有指数)
  • ‘g’ (‘e’:大指数,‘f’:其它情况)
  • ‘G’ (‘E’:大指数,‘f’:其它情况)
f := 100.123456789
fmt.Println(strconv.FormatFloat(f, \'b\', 5, 32)) // 13123382p-17
fmt.Println(strconv.FormatFloat(f, \'e\', 5, 32)) // 1.00123e+02
fmt.Println(strconv.FormatFloat(f, \'E\', 5, 32)) // 1.00123E+02
fmt.Println(strconv.FormatFloat(f, \'f\', 5, 32)) // 100.12346
fmt.Println(strconv.FormatFloat(f, \'g\', 5, 32)) // 100.12
fmt.Println(strconv.FormatFloat(f, \'G\', 5, 32)) // 100.12

字符串转浮点数

通过ParseFloat(s string, bitSize int) (float64, error)可方便地把字符串转为float64;

若要转换为float32,需要bitSize传32,并把结果直接转换为float32即可。

v := "3.1415926535"
r64, _ := strconv.ParseFloat(v, 64)
r, _ := strconv.ParseFloat(v, 32)
r32 := float32(r)
fmt.Println(r64, r32)

以上是关于GO中字符串操作和转换简介的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Go 中将布尔值转换为字符串?

Go开源宝藏Go 语言操作 Redis

Go 字符串操作

Go语言中其他数据与字符串类型的转换

Go语言中其他数据与字符串类型的转换

Go基础之程序结构数据类型