网站首页 > 知识剖析 正文
数组和slice的区别
1.使用方式
数组和slice操作方式差不多, 并且slice包含了数组的基本的操作方式, 如下标、range循环, 还有一些如len()则是多种类型共用,
数组的声明方式很单一,通常这样:
array1 := [6]int{1, 2, 3, 4, 5,6}
array2 := [...]int{1, 2, 3, 4, 5,6}
array3 := [6]int{}
slice的声明方式就非常多样了, 如前面介绍的几种:
var slice1 = []int{1, 2, 3, 4, 5,6}
var slice2 = make([]int, 0, 6)
var slice3 = make([]int, 5, 6)
var slice4 = make([]int, 5)
加上对数组的切片和append操作都会产生数组切片(slice)
数组的创建方式
一维数组
package main
import (
"fmt"
)
//全局
var arr0 [5]int = [5]int{1, 2, 3}
var arr1 = [5]int{1, 2, 3, 4, 5}
var arr2 = [...]int{1, 2, 3, 4, 5, 6}
var str = [5]string{3: "hello world", 4: "tom"}
func main() {
//局部
a := [3]int{1, 2} // 未初始化元素值为 0。
b := [...]int{1, 2, 3, 4} // 通过初始化值确定数组长度。
c := [5]int{2: 100, 4: 200} // 使用引号初始化元素。
d := [...]struct {
name string
age uint8
}{
{"user1", 10}, // 可省略元素类型。
{"user2", 20}, // 别忘了最后一行的逗号。
}
fmt.Println(arr0, arr1, arr2, str)
fmt.Println(a, b, c, d)
}
二维数组
package main
import (
"fmt"
)
//全局
var arr0 [5][3]int
var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
func main() {
//局部
a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。
fmt.Println(arr0, arr1)
fmt.Println(a, b)
}
切片的创建方式
package main
import "fmt"
func main() {
//1.声明切片
var s1 []int
if s1 == nil {
fmt.Println("是空")
} else {
fmt.Println("不是空")
}
// 2.:=
s2 := []int{}
// 3.make()
var s3 []int = make([]int, 0)
fmt.Println(s1, s2, s3)
// 4.初始化赋值
var s4 []int = make([]int, 0, 0)
fmt.Println(s4)
s5 := []int{1, 2, 3}
fmt.Println(s5)
// 5.从数组切片
arr := [5]int{1, 2, 3, 4, 5}
var s6 []int
// 前包后不包
s6 = arr[1:4]
fmt.Println(s6)
}
全局:
var arr = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var slice0 []int = arr[start:end]
var slice1 []int = arr[:end]
var slice2 []int = arr[start:]
var slice3 []int = arr[:]
var slice4 = arr[:len(arr)-1] //去掉切片的最后一个元素
局部:
arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
slice5 := arr[start:end]
slice6 := arr[:end]
slice7 := arr[start:]
slice8 := arr[:]
slice9 := arr[:len(arr)-1] //去掉切片的最后一个元素
2.值传递or引用传递
package main
import (
"fmt"
)
//值拷贝行为会造成性能问题, 通常会建议使用 slice, 或数组指针。
func arrayModify(array [5]int) {
newArray := array
newArray[0] = 88
}
func sliceModify(slice []int) {
newSlice := slice
newSlice[0] = 88
}
func main() {
array := [5]int{1, 2, 3, 4, 5}
slice := []int{1, 2, 3, 4, 5}
arrayModify(array)
sliceModify(slice)
fmt.Println(array)
fmt.Println(slice)
}
输出
[1 2 3 4 5]
[88 2 3 4 5]
实例: 切片和数组之间的拷贝: 拷贝切片
package main
import (
"fmt"
"reflect"
)
func main() {
s := []int{1, 2, 3} //切片的定义方法
var a [3]int //数组的定义方法
var b [3]int //数组的定义方法
//fmt.Println(copy(a, s)) //Error: first argument to copy should be slice; have [3]int
//copy函数第一个参数(目标)只能接收切片参数,我们可以使用[:]方式将数组转换成切片
fmt.Println(s[:2]) //[1 2]
fmt.Println(copy(a[:2], s)) //2 部分拷贝 a[:2] 目标 s 原数组
fmt.Println(a) //[1, 2, 0]
fmt.Println(copy(b[:], s)) //3 全部拷贝 b[:] 目标 s 原数组
fmt.Println(b) //[1, 2, 3]
fmt.Println(reflect.TypeOf(a), reflect.TypeOf(b)) //[3]int [3]int
}
显示的结果
D:\work\src>go run test.go
2
[1 2 0]
3
[1 2 3]
实例: 切片和数组之间的拷贝: 拷贝数组
package main
import (
"fmt"
"reflect"
)
func main() {
a := [...]int{1, 2, 3} //数组的定义方法
s := make([]int, 3) //切片的定义方法
fmt.Println(copy(s, a[:2])) //2 拷贝的数量 s 为目标(参数必须为切片类型) a 为 源 a[:2] 省略low, high, 取长度, :2 代表从开始位置取两个元素
fmt.Println(s) // [1 2 0]
fmt.Println(reflect.TypeOf(a), reflect.TypeOf(s)) //[3]int []int
}
array 与 slice 之间转换
array 转换成 slice (array => slice)
实例1: array => slice 第一种方法
package main
import (
"fmt"
"reflect"
)
func main() {
s := [3]int{1, 2, 3}
var a []int
var b []int
a = s[:] //获取全部
b = s[0:2] //获取部分
fmt.Println(a, b) //[1 2 3] [1 2]
fmt.Println(reflect.TypeOf(a), reflect.TypeOf(b)) //[]int []int
}
实例2: array => slice 第二种方法
package main
import (
"fmt"
"reflect"
)
func main() {
s := [3]int{1, 2, 3}
//var a []int 虽然切片可以这样定义, 但是此种定义方法 导致for遍历时会出现错误
var a = make([]int, 3) //切片的定义方法
for index, item := range s {
a[index] = item
}
fmt.Println(a, reflect.TypeOf(a)) //[1 2 3] []int
}
slice 转换成 array (slice => array)
实例1:
package main
import (
"fmt"
"reflect"
)
func main() {
var arr [3]int //定义数组
s := []int{1, 2, 3} //切片的定义方法
copy(arr[:], s[:]) //copy(dst, src)
fmt.Println(arr, reflect.TypeOf(arr)) //[1 2 3] [3]int
}
实例2:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
//注意: [16]byte 和 []byte 是不同类型 不能直接赋值
var id uuid.UUID //[16]byte
if id[0] == 0 { //判断是否为空的方法
fmt.Println("值为空", len(id), id[0])
}
id = uuid.New()
fmt.Println(id)
uniqueId := uuid.New()
fmt.Println(uniqueId)
// [16]byte => []byte 转换的方法
//方法一
var id2 []byte
id2 = uniqueId[:] // [16]byte => []byte 转换的方法
fmt.Println(id2)
//方法二
var id3 []byte
id3, err := uniqueId.MarshalBinary() // [16]byte => []byte 转换的方法 期本质就是 [:] 封装的方法
if err != nil {
fmt.Println(err)
}
fmt.Println(id3)
// []byte 转换成 [16]byte
id, err = uuid.FromBytes(id3) // // []byte => [16]byte copy(uuid[:], id3[:]) copy(dst, src)
if err != nil {
fmt.Println(err)
}
fmt.Println(id)
}
猜你喜欢
- 2024-11-10 PHP数组学习笔记(1) php数组有哪几种类型
- 2024-11-10 Rust语言入门教程 数组和切片 rust语言例子
- 2024-11-10 javascript自学笔记:Array类型1 javascript自学笔记:array类型1怎么解决
- 2024-11-10 Array.from详解: 语法、功能与应用场景
- 2024-11-10 帮你精通JS:解析与盘点数组array的5类22种方法
- 2024-11-10 10 个实用的 JS 技巧 js常用方法大全
- 2024-11-10 WordPress 内置的数组处理相关函数大全
- 2024-11-10 3分钟短文 | PHP获取函数的代码片段,唯有反射最高效
- 2024-11-10 JS 中的类数组对象如何转换为数组?
- 2024-11-10 Go 中的循环是如何转为汇编的?看完你懂了吗?
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)