23

Go的100天之旅-08字符串

 3 years ago
source link: http://www.cnblogs.com/pirate-hcc/p/13337910.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

目录

简介

字符串在各种编程语言中都是很基础的一种类型,在 Go 中字符串简单理解就是一个数组,数组里面的元素是 byte 类型。因此基本上拥有类似数组的全部特性。例如 len 可以返回字符串的字节数,注意不是字符的长度:

s := "go"
fmt.Println(len(s)) //2

也可以根据下标访问该位置的字节

s := "go"
fmt.Println(s[0]) //103 字符g的ASCII码

字符串也可以类似切片的操作,取其给定范围内的字符串,生成一个新的字符

s := "hello world"
fmt.Println(s[0:5]) // "hello"

fmt.Println(s[:5]) // "hello"
fmt.Println(s[:]) // "hello world"

也可以用 + 操作符,把两个字符串连接成一个新的字符串

s := "hello"
w := "world"

s = s + w //"hello world"

刚开始的时候我们说过,字符串是不可变,这段代码中最后的 s 是一段新的字符串。而不是在开始 s 基础上修改的。同时先要做类似数组那样修改元素的值也是不可以的

s := "hello"
s[1] = 't' //编译时会报错

UTF-8字符

UTF-8UNICODE 的一种变长度的编码表达方式,我们都知道 ASCII 编码是1个字节,但是这也限制了它只能代表128个字符,无非对其它语言的字符进行编码。如果把所有的字符都用统一用32位表示,的确比较简单,但是这样会浪费很多空间,而且历史上的 ASCII 编码的字符也无兼容。 UTF-8 采用1-4个字节表示字符, ASCII 还是只用1个字节,保持兼容。如果第一个字节的是 110 开头,则需要2个字节。1110开头则需要3个字节,11110开头则是4个字节。

0xxxxxxx                             runes 0-127    (ASCII)
110xxxxx 10xxxxxx                    128-2047       (values <128 unused)
1110xxxx 10xxxxxx 10xxxxxx           2048-65535     (values <2048 unused)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx  65536-0x10ffff (other values unused)

Gostring 就是采用 UTF-8 编码,因此无法直接通过下标 i 直接访问第 i 个字符,比如:

s := "你好世界"

fmt.Println(len(s)) //15

上面这段代码运行返回长度是12,如果想要知道有多少个字符可以利用 unicode/utf8 提供的功能来获取:

package main

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	s := "你好世界!"
	fmt.Println(len(s)) //15
	fmt.Println(utf8.RuneCountInString(s)) //5
}

想要分割成单个字符输出可以通过 for range :

func main() {
	s := "你好世界!"
	for i, r := range s {
		fmt.Printf("%d\t%q\t%d\n", i, r, r)
	}
}

//返回
0       '你'    20320
3       '好'    22909
6       '世'    19990
9       '界'    30028
12      '!'    65281

这次遍历都是单个字符的遍历,而不是单个字节。

字符串的常用操作

Go 的标准库提供了丰富的工具,对字符串进行操作,下面简单介绍下常见的操作:

package main

import (
	"fmt"
	"strings"
)

func main() {
	s := "hello"
	fmt.Println(strings.Contains(s, "he"))         //true 是否包含子字符串
	fmt.Println(strings.Replace(s, "he", "eh", 1)) // ehllo 替换第一个

        bytes := []byte(s) //转化为byte数组
	s2 := string(bytes)//byte数组转化为字符串
	fmt.Println(s2)
}

字符串和数字之间的转化也是经常用到的, strconv 里面提供的丰富的功能让它们互相转化

import (
	"fmt"
	"strconv"
)

func main() {
	s := "123"
	i, _:= strconv.Atoi(s) //字符串转化为数字
	fmt.Println(i+2) //125

	x := 123
	var a string = strconv.Itoa(x) //数字转化为字符串
	fmt.Println(a) //123
}

如果想要动态的增加字符串 Go 提供了 Buffer 类型可以动态的增加字符:

package main

import (
	"fmt"
	"bytes"
)

func main() {
	var buf bytes.Buffer
	buf.WriteString("s")

	fmt.Println(buf.String()) //s

	buf.WriteByte('A')
	fmt.Println(buf.String()) //sA
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK