golang 切片 slice 拼接

实例如下:

package main

import "fmt"

func main() {
    s1 := []int{0, 1, 2, 3}
    s2 := []int{4, 5, 6, 7}

    s1 = append(s1, s2...)
    fmt.Println(s1)
}

执行:
// [0 1 2 3 4 5 6 7]

 

 

### 3.4 Go 中的 `byte slice` 与 `slice` 的区别 在 Go 语言中,`slice` 是一种灵活且高效的数据结构,用于表示对底层数组的动态视图。它由一个指针、长度(`len`)和容量(`cap`)组成,分别指向底层数组的起始地址、当前可访问元素的数量以及底层数组的总容量[^1]。 `byte slice` 是 `slice` 的一种具体类型,即 `[]byte`,它专门用于处理字节序列。虽然从底层结构来看,`byte slice` 和其他类型的 `slice` 没有本质区别,但其语义和使用场景具有特定性,尤其是在网络通信、文件读写等涉及二进制数据操作的场合中更为常见。 #### 3.4.1 内部结构差异 所有类型的 `slice` 在运行时都具有相同的内部结构,包括: - 数据指针(指向底层数组) - 长度(当前可访问的元素数量) - 容量(底层数组的总大小) 例如,可以通过 `reflect.SliceHeader` 来手动构造一个 `slice`: ```go var o []byte sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&o)) sliceHeader.Cap = length sliceHeader.Len = length sliceHeader.Data = uintptr(ptr) ``` 尽管如此,`byte slice` 更常用于处理原始字节流,而其他类型的 `slice`(如 `[]int`、`[]string` 等)则用于更通用的集合操作。 #### 3.4.2 内存管理与性能特性 由于 `slice` 是多字段结构体而非单纯的指针,因此对其进行切片拼接操作不会每次都分配新的内存对象,而是共享底层数组,从而提高性能[^1]。例如: ```go s := []int{1, 2, 3, 4} newS := s[1:3] ``` 此时 `newS` 与 `s` 共享底层数组,不会立即复制数据。然而,当修改 `newS` 的内容时,若未触发扩容,则会影响原 `slice` 的数据: ```go newS[0] = 10 fmt.Println(s) // 输出 [1 10 3 4] ``` 对于 `byte slice` 而言,同样适用这一机制。但在某些需要独立副本的场景下,应使用 `copy` 函数进行深拷贝: ```go src := []byte("hello") dst := make([]byte, len(src)) copy(dst, src) ``` 上述方式会调用 `runtime.memmove` 实现底层内存复制[^4],确保两个 `slice` 互不影响。 #### 3.4.3 使用场景与语义差异 虽然 `byte slice` 和其他 `slice` 类型在结构上一致,但它们的用途有所不同: - `byte slice` 主要用于处理原始字节流,适合与 I/O 操作结合使用。 - 其他类型的 `slice` 更适用于构建动态数组,支持任意类型的集合操作。 此外,字符串与 `byte slice` 之间可以相互转换,这种转换不会复制数据,而是通过共享底层数组实现高效操作: ```go s := "hello" bs := []byte(s) // 复制底层数组 str := string(bs) // 再次复制 ``` 其中 `string` 到 `[]byte` 的转换会创建新内存块并复制内容,而 `[]byte` 到 `string` 的转换也会进行复制,以保证字符串的不可变性[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值