Go字符串、数组和切片的应用

本文仅是自己阅读笔记,不正确之处请多包涵和纠正。
原文The way to go

一、从字符串生成字节切片

假设 s 是一个字符串(本质上是一个字节数组),那么就可以直接通过 c := []byte(s) 来获取一个字节的切片 c。另外,您还可以通过 copy 函数来达到相同的目的:copy(dst []byte, src string)。

您还可以将一个字符串追加到某一个字节切片的尾部:

var b []byte
var s string
b = append(b, s…)

二、获取字符串的某一部分

使用 substr := str[start:end] 可以从字符串 str 获取到从索引 start 开始到 end-1 位置的子字符串。同样的,str[start:] 则表示获取从 start 开始到 len(str)-1 位置的子字符串。而 str[:end] 表示获取从 0 开始到 end-1 的子字符串。

三、字符串和切片的内存结构

在内存中,一个字符串实际上是一个双字结构,即一个指向实际数据的指针和记录字符串长度的整数(见图 7.4)。因为指针对用户来说是完全不可见,因此我们可以依旧把字符串看做是一个值类型,也就是一个字符数组。

字符串 string s = “hello” 和子字符串 t = s[2:3] 在内存中的结构可以用下图表示:
Go字符串、数组和切片的应用_第1张图片

四、修改字符串中的某个字符

Go 语言中的字符串是不可变的,也就是说 str[index] 这样的表达式是不可以被放在等号左侧的。如果尝试运行 str[i] = 'D' 会得到错误:cannot assign to str[i]

因此,您必须先将字符串转换成字节数组,然后再通过修改数组中的元素值来达到修改字符串的目的,最后将字节数组转换回字符串格式。

例如,将字符串 “hello” 转换为 “cello”:

s := "hello"
c := []byte(s)
c[0] = 'c'
s2 := string(c) // s2 == "cello"

所以,您可以通过操作切片来完成对字符串的操作。

五、append 函数常见操作

1、将切片 b 的元素追加到切片 a 之后:a = append(a, b...)
2、复制切片 a 的元素到新的切片 b 上:

b = make([]T, len(a))
copy(b, a)

3、删除位于索引 i 的元素:a = append(a[:i], a[i+1:]...)
4、切除切片 a 中从索引 i 至 j 位置的元素:a = append(a[:i], a[j:]...)
5、为切片 a 扩展 j 个元素长度:a = append(a, make([]T, j)...)
6、在索引 i 的位置插入元素 x:a = append(a[:i], append([]T{x}, a[i:]...)...)
7、在索引 i 的位置插入长度为 j 的新切片:a = append(a[:i], append(make([]T, j), a[i:]...)...)
8、在索引 i 的位置插入切片 b 的所有元素:a = append(a[:i], append(b, a[i:]...)...)
9、取出位于切片 a 最末尾的元素 x:x, a = a[len(a)-1], a[:len(a)-1]
10、将元素 x 追加到切片 a:a = append(a, x)

因此,您可以使用切片和 append 操作来表示任意可变长度的序列。

六、切片和垃圾回收

切片的底层指向一个数组,该数组的实际容量可能要大于切片所定义的容量。只有在没有任何切片指向的时候,底层的数组内存才会被释放,这种特性有时会导致程序占用多余的内存

var digitRegexp = regexp.MustCompile("[0-9]+")

func FindDigits(filename string) []byte {
    b, _ := ioutil.ReadFile(filename)
    return digitRegexp.Find(b)
}

这段代码可以顺利运行,但返回的 []byte 指向的底层是整个文件的数据。**只要该返回的切片不被释放,垃圾回收器就不能释放整个文件所占用的内存。**换句话说,一点点有用的数据却占用了整个文件的内存

想要避免这个问题,可以通过拷贝我们需要的部分到一个新的切片中:

func FindDigits(filename string) []byte {
   b, _ := ioutil.ReadFile(filename)
   b = digitRegexp.Find(b)
   c := make([]byte, len(b))
   copy(c, b)
   return c
}

你可能感兴趣的:(Golang)