go 数组 字符串 切片
数组
数组定义方式
var a [3]int // 定义长度为3的int型数组, 元素全部为0
var b = [...]int{1, 2, 3} // 定义长度为3的int型数组, 元素为 1, 2, 3
var c = [...]int{2: 3, 1: 2} // 定义长度为3的int型数组, 元素为 0, 2, 3
var d = [...]int{1, 2, 4: 5, 6} // 定义长度为6的int型数组, 元素为 1, 2, 0, 0, 5, 6
- 数组类型包含基础类型和数组长度
- 数组复制是整体复制
- 数组名称代表整个数组而不是数组起始地址
- 可以用&取起始地址,传参,防止大量复制
字符串
- 不可变字节序列,是一个只读的字节数组
- 长度不是字符串类型的一部分
- 默认编码是utf8, for range 语法不支持非UTF8编码字符串的遍历
- 字符串复制不会涉及底层数组复制,参考下面字符串的结构体, data指针和len长度的复制
- len(s)求的是[]byte的长度
- 字符串底层[]byte, rune底层int32
- []rune 是一个 []int32, rune表示每个Unicode码点,目前只用了21位
type StringHeader struct {
Data uintptr
Len int
}
切片
切片定义
var (
a []int // nil切片, 和 nil 相等, 一般用来表示一个不存在的切片
b = []int{} // 空切片, 和 nil 不相等, 一般用来表示一个空的集合
c = []int{1, 2, 3} // 有3个元素的切片, len和cap都为3
d = c[:2] // 有2个元素的切片, len为2, cap为3
e = c[0:2:cap(c)] // 有2个元素的切片, len为2, cap为3
f = c[:0] // 有0个元素的切片, len为0, cap为3
g = make([]int, 3) // 有3个元素的切片, len和cap都为3
h = make([]int, 2, 3) // 有2个元素的切片, len为2, cap为3
i = make([]int, 0, 3) // 有0个元素的切片, len为0, cap为3
)
切片遍历方式
for i := range a {
fmt.Printf("a[%d]: %d\n", i, a[i])
}
for i, v := range b {
fmt.Printf("b[%d]: %d\n", i, v)
}
for i := 0; i < len(c); i++ {
fmt.Printf("c[%d]: %d\n", i, c[i])
}
-
切片复制与字符串一样, 复制切片头信息reflect.SliceHeader
-
append函数和copy函数组合使用
-
append(s1, s2...), s2自动解包,将s2切片内数据复制到s1
-
切片高效的要点是要降低内存分配的次数,尽量保证append操作不会超出cap的容量
-
避免切片内存泄漏
-
func FindPhoneNumber(filename string) []byte { b, _ := ioutil.ReadFile(filename) b = regexp.MustCompile("[0-9]+").Find(b) return append([]byte{}, b...) } //一个小的需求可能导致需要长时间保存整个文件数据,可以将结果复制到一个新的切片
-
var a []*int{ ... } a[len(a)-1] = nil // GC回收最后一个元素内存 a = a[:len(a)-1] // 从切片删除最后一个元素 **若没有第二局,被删除的元素依然被底层数组引用, //从而导致不能及时被GC回收
-
-
为了安全,当两个切片类型
[]T
和[]Y
的底层原始切片类型不同时,Go语言是无法直接转换类型的。可以使用反射进行转换,前提是保证转化的数据安全有效
posted on 2019-04-18 20:06 slowlyChange 阅读(1656) 评论(0) 编辑 收藏 举报