Files
the-way-to-go_ZH_CN/eBook/07.6.md
Unknwon 9aed73c38b 7.6.4
2015-01-17 21:05:42 +08:00

70 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 7.6 字符串、数组和切片的应用
## 7.6.1 从字符串生成字节切片
假设 s 是一个字符串(本质上是一个字节数组),那么就可以直接通过 `c := []bytes(s)` 来获取 c 为一个元素类型为字节的切片。另外,您还可以通过 copy 函数来实现:`copy(dst []byte, src string)`.
同样的,还可以使用 for-range 语法来获得每个元素Listing 7.13—for_string.go
```go
package main
import "fmt"
func main() {
s := "\u00ff\u754c"
for i, c := range s {
fmt.Printf("%d:%c ", i, c)
}
}
```
输出:
0:ÿ 2:界
我们发现Unicode 字符会占用 2 个字节,有些甚至需要 3 个或者 4 个字节来进行表示。如果发现错误的 UTF8 字符,则该字符会被设置为 U+FFFD 并直接向前移动一个字节。和字符串转换一样,您同样可以使用 `c := []int(s)` 语法,这样切片中的每个 int 都会包含对应的 Unicode 代码,因为字符串中的每次字符都会对应一个整数。类似的,您也可以将字符串转换为元素类型为 rune 的切片:`r := []rune(s)`
可以通过代码 `len([]int(s))` 来获得字符串中字符的数量,但使用 `utf8.RuneCountInString(s)` 效率会更高一点。
您还可以将一个字符串追加到某一个字符数组的尾部:
```go
var b []byte
var s string
b = append(b, s...)
```
## 7.6.2 获取字符串的某一部分
使用 `substr := str[start:end]` 可以从字符串 str 获取到从索引 start 开始到 end-1 位置的子字符串。同样的,`str[start:]` 则表示获取从 start 开始到 len(str)-1 位置的子字符串。而 `str[:end]` 表示获取从 0 开始到 end-1 的子字符串。
## 7.6.3 字符串和切片的内存结构
在内存中,一个字符串实际上是一个双字结构,即一个指向实际数据的指针和记录字符串长度的整数(见图 7.4)。因为指针对用户来说是完全不可见,因此我们可以依旧把字符串看做是一个值类型,也就是一个字符数组。
字符串 `string s = "hello"` 和子字符串 `t = s[2:3]` 在内存中的结构可以用下图表示:
![](images/7.6_fig7.4.png)
## 7.6.4 修改字符串中的某个字符
Go 语言中的字符串是不可变的,也就是说 `str[index]` 这样的表达式是不可以被放在等号左侧的。如果尝试运行 `str[i] = D` 会得到错误:`cannot assign to str[i]`
因此,您必须先将字符串转换成字节数组,然后再通过修改数组中的元素值来达到修改字符串的目的,最后将字节数组转换会字符串格式。
例如,将字符串 "hello" 转换为 "cello"
```go
s := "hello"
c := []byte(s)
c[0] = c
s2 := string(c) // s2 == "cello"
```
所以,您可以通过操作切片来完成对字符串的操作。
## 7.6.5 字节数组对比函数
180