golang中你不知道的 string

golang中你不知道的 stringgit

字符串对于一篇博客文章来讲彷佛太简单了,可是一个简单的东西想用好,其实也不容易。github

遍历字符串

package main

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	const sample = "我爱golang"
	for i := 0; i < len(sample); i++ {
		runeValue, _ := utf8.DecodeRuneInString(sample[i:])
		fmt.Printf("position:%v, value:%c \n", i, runeValue)
	}
}
复制代码
position:0, value:我 
position:1, value:� 
position:2, value:� 
position:3, value:爱 
position:4, value:� 
position:5, value:� 
position:6, value:g 
position:7, value:o 
position:8, value:l 
position:9, value:a 
position:10, value:n 
position:11, value:g
复制代码

输出的是每个字节。 若是想输出字符呢?golang

package main

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	const sample = "我爱golang"
	for i, s := 0, 0; i < len(sample); i = i + s {
		runeValue, size := utf8.DecodeRuneInString(sample[i:])
		fmt.Printf("position:%v, value:%c \n", i, runeValue)
		s = size
	}
}
复制代码

输出bash

position:0, value:我 
position:3, value:爱 
position:6, value:g 
position:7, value:o 
position:8, value:l 
position:9, value:a 
position:10, value:n 
position:11, value:g 
复制代码

还有更方便的吗?ui

package main

import (
	"fmt"
)

func main() {
	const sample = "我爱golang"
	for key, v := range sample {
		fmt.Printf("position:%v, value:%c \n", key, v)
	}
}
复制代码

输出编码

position:0, value:我 
position:3, value:爱 
position:6, value:g 
position:7, value:o 
position:8, value:l 
position:9, value:a 
position:10, value:n 
position:11, value:g 
复制代码
  • golang字符串是由字节构成的,所以索引它们会产生字节,而不是字符
  • 经过unicode、utf-8等编码方式,从[]byte中解码字符串

字符串的长度

package main

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	str := "我爱golang"
	fmt.Println(len(str), "len bytes")
	fmt.Println(utf8.RuneCountInString(str), "len characters") // 更快
	fmt.Println(len([]rune(str)), "len characters")
}
复制代码

输出spa

12 len bytes
8 len characters
8 len characters
复制代码
  • golang对字符串的底层处理,采用的是[]byte,实际存储的值是一个uint8类型的;
  • 采用UTF-8编码英文字符,每一个字符只占用一个byte,而中文须要占用3个byte,所以长度是12;
  • utf8会自动判断每一个字符编码占用了几个byte,很清晰的展现了 Golang 对 string 的处理原理;
  • for range string 每次迭代会解码一个 utf-8 编码的字符。

修改字符串

package main

import "fmt"

func main() {
	str := "golang"
	c := []byte(str)
	c[0] = 'c'
	s2 := string(c)
	fmt.Println(s2)
}
复制代码

输出code

colang
复制代码

拼接字符串

package main

import (
	"bytes"
	"fmt"
)

func main() {
	str := "我爱"
	str2 := "golang"
	// 该方案每次合并会建立一个新的字符串
	fmt.Println(str + str2)

	// 该方案更更快,直接链接底层的 []byte
	var buffer bytes.Buffer
	buffer.WriteString(str)
	buffer.WriteString(str2)
	fmt.Println(buffer.String())
}

复制代码

WriteString更快的缘由,见源码直接底层[]byte链接blog

func (b *Buffer) WriteString(s string) (n int, err error) {
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(len(s))
	if !ok {
		m = b.grow(len(s))
	}
	return copy(b.buf[m:], s), nil
}
复制代码

参考

更多内容,欢迎关注个人Github索引

相关文章
相关标签/搜索