首页 > 其他分享 >golang中的数组和切片

golang中的数组和切片

时间:2024-05-31 21:43:33浏览次数:12  
标签:切片 slice fmt cap len golang 数组 Printf

package main

import (
	"fmt"
	"time"
)

func main() {
	x := [...]int{1, 2, 3} // 数组的声明中可以使用...来代替具体的数字
	y := x                 // 数组的赋值是全拷贝方式,所以对新数组的修改不影响原始数组
	y[0] = 4
	// z := append(x, 2)   // 数组不可以使用append 操作。
	fmt.Printf("&x: %p, &y: %p\n", &x, &y)
	fmt.Printf("x: %v, y: %v\n", x, y)

	m := []int{1, 2, 3}
	n := m // 切片的赋值仅仅将索引部分拷贝,所以对新切片的修改会影响到原始切片的数据
	n[0] = 4
	fmt.Printf("&m: %p, &n: %p\n", &m, &n)
	fmt.Printf("m: %v, n: %v\n", m, n)

	slice := []int{1, 2, 3, 4, 5, 6}
	fmt.Printf("slide len: %d, cap: %d\n", len(slice), cap(slice))          // 原始切片的长度和容量:slide len: 6, cap: 6
	subSlice := slice[1:4]                                                  // 子切片的长度和容量,注意这里的容量为新切片在原始切片位置开始的剩余容量。
	fmt.Printf("subSlide len: %d, cap: %d\n", len(subSlice), cap(subSlice)) // subSlide len: 3, cap: 5

	slice = append(slice, 7)                                       // 容量总是 以x2的方式增长。
	fmt.Printf("slide len: %d, cap: %d\n", len(slice), cap(slice)) // slide len: 7, cap: 12
	slice = append(slice, 8, 9, 10, 11, 12, 13)
	fmt.Printf("slide len: %d, cap: %d\n", len(slice), cap(slice)) // 再次翻倍: cap:24

	i := []int{1, 2, 3}
	j := i[:]
	j[0] = 4                               // 切片是对现有数据(内存块)的索引,所以,对切片内的元素的修改会影响到所以该数据的所有切片
	fmt.Printf("&i: %p, &j: %p\n", &i, &j) //
	fmt.Printf("i: %v, j: %v\n", i, j)     // i: [4 2 3], j: [4 2 3]

	// 这可能是最难理解的地方,因为cap导致的底层数据被拷贝,上层行为产生差异。
	// 如果底层数组的容量不足以容纳附加的元素,则 append() 函数将分配一个新的、更大容量的数组保存结果。
	// 如果 append 操作之后创建了一个更大的数组,则新切片将不在与原来的子切片共享相同的底层数组。
	a := []int{1, 2, 3}     // a 的长度为3, 容量为3
	b := append(a, 4, 5, 6) // b 的长度为6, 容量为6,因为原有内存位置的容量不足以保存新的容量,所以a和b元素的底层物理位置并不相同
	b[0] = 4                // 对b的修改不影响a的值
	fmt.Printf("a: %v, b: %v\n", a, b)

	c := append(a)
	c[0] = 2
	d := a[:2]
	d = append(d, 7)
	fmt.Printf("a: %v, c: %v, d: %v\n", a, c, d) // c 和d 操作均可以在原有容量中完成,所以对各个切片元素的修改会影响到a切片

	fmt.Printf("[]int{} len: %d, cap: %d\n", len([]int{}), cap([]int{})) // 空的slice的长度和容量都是0

	testCopy()
	benchmarkArrayVSSlice()
}

func testCopy() {
	a := []int{1, 2, 3, 4, 5}
	b := make([]int, 2, 4)
	n := copy(b, a)                           // copy 函数将元素复制,而不是让b索引原slice
	fmt.Printf("copied from a to b: %d\n", n) // 复制数量和原slice及目标slice的长度有关系
	fmt.Printf("b: %v\n", b)
	b[0] = 4 // 对复制后的slice改动不会影响原有slice,因为是深度拷贝
	fmt.Printf("a: %v, b: %v\n", a, b)
}

/*
重要:
	不同slice,可能会共享相同的底层位置,
	为了能够将GC将不必要的内存回收,尤其是大slice占据的内容,
	我们可以使用copy的方式将大slice中关注的部分深度拷贝存储,而不是引用大slice。
	这样,大slice就可以及时的被GC回收掉。
*/

// 值分配、参数传递、使用 range 关键字循环等,都涉及值拷贝。值大小越大,拷贝的代价就越大
// 所以,在出现性能问题的时候要考虑下是否可以使用 slice代替数组提升效率。
func benchmarkArrayVSSlice() {
	a := [10000]int{}
	b := make([]int, 10000)
	var s, e time.Time

	s = time.Now()
	for range a {
	}
	e = time.Now()
	fmt.Printf("loop array: %d\n", e.Sub(s).Nanoseconds())

	s = time.Now()
	for range b {
	}
	e = time.Now()
	fmt.Printf("loop slice: %d\n", e.Sub(s).Nanoseconds())
}


标签:切片,slice,fmt,cap,len,golang,数组,Printf
From: https://www.cnblogs.com/zongzw/p/18225324

相关文章

  • golang函数使用基础
    函数介绍有其他语言基础的话就没啥介绍的,基本语法:funcfunctionName(形参列别)(返回值列表){执行语句return返回值列表}例子:funcgetSum(n1int,n2int)int{varresint=n1+n2 returnres}包实际就创建不同的文件夹,存放程序文件。Go的每一个文......
  • 黑客团伙利用Python、Golang和Rust恶意软件袭击印国防部门;OpenAI揭秘,AI模型如何被用于
    巴黑客团伙利用Python、Golang和Rust恶意软件袭击印度国防部门!与巴基斯坦有联系的TransparentTribe组织已被确认与一系列新的攻击有关,这些攻击使用Python、Golang和Rust编写的跨平台恶意软件,针对印度政府、国防和航空航天部门。“这一系列活动从2023年底持续到2024年4月......
  • 123. 连续子数组最大和(卡码网周赛第十九期)
    123.连续子数组最大和(卡码网周赛第十九期(23年小红书提前批笔试真题))题目描述小红拿到了一个数组,她希望进行最多一次操作:将一个元素修改为x。小红想知道,最终的连续子数组最大和最大是多少?输入第一行输入一个正整数t,代表询问次数。对于每次询问,输入两行:第一行输入两......
  • 我有一个数组 [ 1,2 , 3,-4,-1,4 ],希望按 [-4,1,-1,2,3,4] 的顺序排列。
    我有一个数组[1,2,3,-4,-1,4],希望按照[-4,1,-1,2,3,4]的顺序排序。想要按照负数、正数、绝对值大小排序。我可以帮实现。以下是使用Python代码实现此排序逻辑的方法:defspecial_sort(nums):"""按照负数、正数、绝对值大小排序。Args:nu......
  • Golang GRPC 环境 问题
    生成文件执行protoc--go_out=.--go_opt=paths=source_relative--go-grpc_out=.--go-grpc_opt=paths=source_relativeservice.proto 报下列错处理方法1.'protoc-gen-go'不是内部或外部命令,也不是可运行的程序或批处理文件。a.检查gopath目录(%GOPATH%\)的bin文件夹,是否有......
  • QT_5.2_matlab组合多维数组
    完整代码示例以下是一个完整的代码示例,展示如何将多个测试数据拼接成一个四维数组:%示例测试数据nn=10;%假设有10个测试样本TestData=cell(nn,6);%创建一个包含10个样本的单元格数组,每个样本包含6个二维矩阵%生成一些随机数据作为示例fork=1:nnforj=1......
  • 代码随想录算法训练营第第23天 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索
    修剪二叉搜索树这道题目比较难,比添加增加和删除节点难的多,建议先看视频理解。题目链接/文章讲解:https://programmercarl.com/0669.修剪二叉搜索树.html视频讲解:https://www.bilibili.com/video/BV17P41177ud/***@param{TreeNode}root*@param{number}low*@pa......
  • golang import 导入的四种方式
     1标准导入:import"package_name" 2导入别名:import(alias"package_name") 3匿名导入:import(_"package_name") 4点导入:import(."package_name") 下面做详细解释:Go语言最常见的导入方式是标准导入,格式如下:import&qu......
  • 程序分享--常见算法/编程面试题:不使用额外数组空间,原地移除数组中给定元素
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;有意找工作的同学,请参考博主的原创:《面试官心得--面试前应该如何准备》,《面试官心得--面试时如何进行自我介绍》, 《做好面试准备,迎接2024金三银四》。或关注博主免费专栏【程序......
  • 前缀和数组
    //前缀和数组preSum[]:preSum[i]记录nums[0,i-1]区间的累加和classex_preSum{private:vector<int>preSum;public:ex_preSum(vector<int>nums){preSum.resize(nums.size()+1);//原数组下标[0,n-1]。preS......