Golang数组和slice

2023-09-18 14:21:31

Golang数组和Slice(切片)

Go语言中数组长度固定不可变动,slice则可以增长缩短(使用较多)

一、数组类型

Go语言中数组长度固定, 索引从0开始计数。需要注意数组的长度一开始必须是固定的,且不同长度的数组其表示不同的数据类型,相同的数组可以进行 ‘==’ 比较。数组作为函数参数是使用的是形参的方式,函数内不可改变其值,需要使用数组指针的方式进行传值。

1.数组初始化

数组的长度可以写在 [ ] 中([10]int)或者使用 自动从 {1, 2, 3} 初始化参数中确定。数组的初始值默认为数组元素类型的零值

package main

import (
	"fmt"
)

const (
	a = iota
	b
	c
	d
)

func main() {
	//数组初始化
	s := [3]int{1, 2, 3}
	//索引对应的值
	f := [...]string{a: "fht", b: "fyq", c: "zcy", d: "zcx"}
	//长度为11,num[10]=-1,其余为‘0’
	num := [...]int{10: -1}
	fmt.Println(s)
	fmt.Println(f)
	fmt.Println(num)
}
// 输出
//[1,2,3]
// [fht fyq zcy zcx]
// [0 0 0 0 0 0 0 0 0 0 -1]

2.数组相等判断

两个类型相同,长度相同的数组可以相互判断是否相等。

package main

import (
	"fmt"
)
func main() {
	s := [3]int{1, 2, 3}
	ss := [3]int{2, 3, 4}
	if s == ss {
		fmt.Println("s == ss")
	} else {
		fmt.Println("s != ss")
	}
}
// 输出
// s != ss

3.数组作为函数的传递参数

不同于其他语言,Go语言的数组作为形参传递给函数,函数内部对数组的操作不影响外部数组。若要改变外部数组的值,需要传递数值指针的值。

package main

import (
	"fmt"
)
func main() {
	s := [3]int{1, 2, 3}
	changeS1(s)
	fmt.Println(s)
	changeS2(&s)
	fmt.Println(s)
}

//形参
func changeS1(s [3]int) {
	for i, _ := range s {
		s[i] = 0
		//fmt.Println(v)
	}
}

//数组指针
func changeS2(s *[3]int) {
	for i, _ := range s {
		s[i] = 0
		//fmt.Println(v)
	}
}
// 输出
// [1 2 3]
// [0 0 0]

二、slice类型

Go语言的切片类型是常用的数据类型,该类型通过指针将数组扩展为可扩容的数据变量。slice三个属性:指针、长度和容量
注意: 一个底层数组可以被多个切片使用,底层数组只有在没有被引用时才会进行GC,需要注意数组的及时释放,不然会造成内存浪费或者内存溢出。

1、slice初始化

package main

import (
	"fmt"
)

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	b := make([]int, 2, 5)
	// b = a[:3]
	b[0] = 1
	b[1] = 2
	fmt.Printf("len(a): %d\n%v\n", len(a), a)
	fmt.Printf("len(b): %d\n%v\n", len(b), b)
}

// 输出
// len(a): 9
// [1 2 3 4 5 6 7 8 9]
// len(b): 2
// [1 2]

2、slice的引用

若slice的引用超过了被引用对象的容量 cap(s) 则会宕机,但是若是超过的是其长度len(s) 则只会发生扩容。
e.g

package main

import (
	"fmt"
)

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	b := a[:4]
	c := b[:7]
	//d := a[:20]   会报错,超过了引用对象的cap
	fmt.Printf("cap(a): %d\n", cap(a))
	fmt.Printf("len(a): %d\n%v\n", len(a), a)
	fmt.Printf("len(b): %d\n%v\n", len(b), b)
	fmt.Printf("len(c): %d\n%v\n", len(c), c)
}

// 输出
// cap(a): 9
// len(a): 9
// [1 2 3 4 5 6 7 8 9]
// len(b): 4
// [1 2 3 4]
// len(c): 7
// [1 2 3 4 5 6 7]

注:copy(dst, src)函数只会复制最小长度。

3、append函数

向切片末尾添加元素,需要注意该函数如果发生扩容则会改变切片指向的底层数组,故每次使用时需要对其重新赋值,例如s[ ], 使用:s = append(s, 1, 2, 3),执行函数之后s可能已经不是之前的s数组了,同理,当我们在调用函数时,如果改变了切片的容量,也需要重新赋值,不然其底层数组不会改变,则其值也不会变。

package main

import (
	"fmt"
)

func main() {
a := []int{1, 2, 3, 4, 5, 6}
	fmt.Printf("cap(a): %d\n", cap(a))
	fmt.Printf("len(a): %d\n%v\n", len(a), a)

	testAppend1(a)
	fmt.Printf("cap(a): %d\n", cap(a))
	fmt.Printf("len(a): %d\n%v\n", len(a), a)

	a = testAppend2(a)
	fmt.Printf("cap(a): %d\n", cap(a))
	fmt.Printf("len(a): %d\n%v\n", len(a), a)
}
//该函数无法没有返回扩容之后的数组,故原切片不会变化
func testAppend1(a []int) {
	a = append(a, 1, 2, 3, 4)
}
//该函数更新了扩容之后的数组,故原切片发生变化
func testAppend2(a []int) []int {
	a = append(a, 7, 8, 9)
	return a
}
// 输出
// cap(a): 6
// len(a): 6
// [1 2 3 4 5 6]
// cap(a): 6
// len(a): 6
// [1 2 3 4 5 6]
// cap(a): 12
// len(a): 9
// [1 2 3 4 5 6 7 8 9]

4、slice就地修改

避免重新分配数组。
e.g.
编写函数,去除[ ]string 中相邻的重复字符串元素。

package main

import (
	"fmt"
)

func main() {
	str := []string{"123", "456", "456", "789"}
	str = delsimple(str)
	fmt.Println(str)
}

func delsimple(s []string) []string {
	var p int = 1
	lent := len(s)
	for i := 1; i < lent; i++ {
		if s[i] != s[i-1] {
			s[p] = s[i]
			p++
		}
	}
	return s[:p]
}
// 输出
// [123 456 789]
更多推荐

微软(TTS)文本转语音服务API实现

此博客实现与java实现微软文本转语音(TTS)经验总结_javatts_${简简单单}的博客-CSDN博客之上,首先感谢博客源码的提供,本人在上面添加了一些详细的注释,方便大家跟好的理解和使用,毕竟我已经用原文调试了一下午才调通,一些细节的问题给大家标注出来,免得浪费大家的时间,下面直接开始代码吧!首先大家需要去微软

NFTScan 正式上线 TON NFTScan 浏览器!

2023年9月12号,NFTScan团队正式对外发布了TONNFTScan基础设施,将为TON生态的NFT开发者和用户提供简洁高效的NFT数据搜索查询服务。NFTScan作为全球领先的NFT数据基础设施服务商,TON是继Bitcoin、Ethereum、BNBChain、Polygon、Solana、Arbitrum、

删库跑路?掌握rm命令的技巧,高效删除文件和目录!

文章目录前言1.什么是rm命令?简介:认识这位特殊成员,他到底是好还是坏?2.如何使用rm命令?语法和选项:掌握rm命令的技巧和要点3.删除文件使用示例:轻松删除文件,释放磁盘空间4.删除目录使用示例:彻底删除目录及其内容,整理文件系统5.强制删除使用示例:一键强制删除,不再犹豫6.交互式删除使用示例:审慎删除,确保操

安防监控视频AI智能分析网关:人流量统计算法的应用场景汇总

TSINGSEE青犀人流量检测算法是内置在智能分析网关中的一种能够通过AI分析和计算人群数量以及密度的算法技术,在提升城市管理效率、改善用户体验和增加安全性方面发挥着重要作用。人流量检测算法在许多领域都有广泛的应用,如智慧城市、智慧交通、智慧景区等。人流量检测算法在一网统管与智慧城市中,可以用于日常交通管理中,例如实时

MyBatis-Plus的常用注解

一、@TableName在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表,由此得出结论,MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定,即实体类型决定,且默认操作的表名和

Challenges and Applications of Large Language Models

本文是LLM系列文章,针对《ChallengesandApplicationsofLargeLanguageModels》的翻译。大语言模型的挑战与应用摘要1引言2挑战3应用3.1聊天机器人3.2计算生物学3.3计算机程序3.4创造性工作3.5知识工作3.6法律3.7医学3.8推理3.9机器人和嵌入式代理3.10社会科

Continual Pre-Training of Large Language Models: How to (re)warm your model?

本文是LLM系列文章,针对《ContinualPre-TrainingofLargeLanguageModels:Howto(re)warmyourmodel?》的翻译。大型语言模型的持续预训练:如何(重新)预热你的模型摘要1引言2设置3相关工作4持续加热5讨论/局限性6结论摘要大型语言模型(LLM)通常在数十亿个to

【Python】多线程编程 ② ( 进程与线程 | 进程的内存空间 | 并行执行概念 | 线程的创建和执行 | threading.Thread() 函数解析 )

文章目录一、进程与线程1、进程的内存空间2、线程之间的共享内存3、并行执行概念二、Python多线程编程1、线程的创建和执行2、threading.Thread()函数解析3、代码示例-线程创建运行4、代码示例-线程并行运行一、进程与线程1、进程的内存空间在操作系统中,进程之间的内存空间是隔离的,不同的进程拥有各自的内

前端面试八股(持续更新)

文章目录一、CSS1.说一下CSS的盒模型。2.CSS选择器的优先级?3.隐藏元素的方法有哪些?4.px和rem的区别是什么?5.重绘重排有什么区别?6.让一个元素水平垂直居中的方式有哪些?7.CSS的哪些属性哪些可以继承?哪些不可以继承?8.有没有用过预处理器?二、JavaSscipt1.JS由哪三部分组成?2.JS

Maven

目录Maven安装及配置使用IDEA创建Maven项目MavenPOM​编辑什么是Maven?Maven是一个Java项目管理和构建工具,它可以定义项目结构、项目依赖,并使用统一的方式进行自动化构建,是Java项目不可缺少的工具。主要作用?Maven就是是专门为Java项目打造的管理和构建工具,它的主要功能有:标准化的

实用!Python大型Excel文件处理:快速导入、导出与批量处理

Python是一种功能强大的编程语言,它提供了丰富的库和工具,使得处理大型Excel文件变得容易和高效。下面将介绍如何使用Python快速导入、导出和批量处理大型Excel文件。下面是一些建议和实践经验,希望能对你有所帮助。一、Excel文件处理库的选择在开始之前,我们需要选择一个适合处理Excel文件的库。以下是一些

热文推荐