首页 > 其他分享 >Go的切片

Go的切片

时间:2024-11-26 19:59:06浏览次数:6  
标签:int fmt len 切片 var Go numSlice2

Go的切片

为什么要使用切片

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。
它非常灵活,支持自动扩容。

切片是一个引用类型,它的内部结构包含地址、长度和容量。

声明切片类型的基本语法如下:

var name [] T

其中:

  • name:表示变量名
  • T:表示切片中的元素类型

举例

// 声明切片,把长度去除就是切片
var slice = []int{1,2,3}
fmt.Println(slice)

关于nil的认识

当你声明了一个变量,但却还并没有赋值时,golang中会自动给你的变量赋值一个默认的零值。这是每种类型对应的零值。

  • bool:false
  • numbers:0
  • string:“”
  • pointers:nil
  • slices:nil
  • maps:nil
  • channels:nil
  • functions:nil

nil表示空,也就是数组初始化的默认值就是nil

var slice2 [] int
fmt.Println(slice2 == nil)

运行结果

true

切片的遍历

切片的遍历和数组是一样的

var slice = []int{1,2,3}
for i := 0; i < len(slice); i++ {
    fmt.Print(slice[i], " ")
}

基于数组定义切片

由于切片的底层就是一个数组,所以我们可以基于数组来定义切片

// 基于数组定义切片
a := [5]int {55,56,57,58,59}
// 获取数组所有值,返回的是一个切片
b := a[:]
// 从数组获取指定的切片
c := a[1:4]
// 获取 下标3之前的数据(不包括3)
d := a[:3]
// 获取下标3以后的数据(包括3)
e := a[3:]

运行结果

[55 56 57 58 59]
[55 56 57 58 59]
[56 57 58]
[55 56 57]
[58 59]

同理,我们不仅可以对数组进行切片,还可以切片在切片

切片的长度和容量

切片拥有自己的长度和容量,我们可以通过使用内置的len)函数求长度,使用内置的cap()
函数求切片的容量。

切片的长度就是它所包含的元素个数。

切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。切片s的长度和容量可通过表达式len(s)和cap(s)来获取。

举例

// 长度和容量
s := []int {2,3,5,7,11,13}
fmt.Printf("长度%d 容量%d\n", len(s), cap(s))

ss := s[2:]
fmt.Printf("长度%d 容量%d\n", len(ss), cap(ss))

sss := s[2:4]
fmt.Printf("长度%d 容量%d\n", len(sss), cap(sss))

运行结果

长度6 容量6
长度4 容量4
长度2 容量4

为什么最后一个容量不一样呢,因为我们知道,经过切片后sss = [5, 7] 所以切片的长度为2,但是一因为容量是从2的位置一直到末尾,所以为4

切片的本质

切片的本质就是对底层数组的封装,它包含了三个信息

  • 底层数组的指针
  • 切片的长度(len)
  • 切片的容量(cap)

举个例子,现在有一个数组 a := [8]int {0,1,2,3,4,5,6,7},切片 s1 := a[:5],相应示意图如下

切片 s2 := a[3:6],相应示意图如下:

使用make函数构造切片

我们上面都是基于数组来创建切片的,如果需要动态的创建一个切片,我们就需要使用内置的make函数,格式如下:

make ([]T, size, cap)

其中:

  • T:切片的元素类型
  • size:切片中元素的数量
  • cap:切片的容量

举例:

// make()函数创建切片
fmt.Println()
var slices = make([]int, 4, 8)
//[0 0 0 0]
fmt.Println(slices)
// 长度:4, 容量8
fmt.Printf("长度:%d, 容量%d", len(slices), cap(slices))

需要注意的是,golang中没办法通过下标来给切片扩容,如果需要扩容,需要用到append

slices2 := []int{1,2,3,4}
slices2 = append(slices2, 5)
fmt.Println(slices2)
// 输出结果 [1 2 3 4 5]

同时切片还可以将两个切片进行合并

// 合并切片
slices3 := []int{6,7,8}
slices2 = append(slices2, slices3...)
fmt.Println(slices2)
// 输出结果  [1 2 3 4 5 6 7 8]

需要注意的是,切片会有一个扩容操作,当元素存放不下的时候,会将原来的容量扩大两倍

使用copy()函数复制切片

前面我们知道,切片就是引用数据类型

  • 值类型:改变变量副本的时候,不会改变变量本身
  • 引用类型:改变变量副本值的时候,会改变变量本身的值

如果我们需要改变切片的值,同时又不想影响到原来的切片,那么就需要用到copy函数

// 需要复制的切片
var slices4 = []int{1,2,3,4}
// 使用make函数创建一个切片
var slices5 = make([]int, len(slices4), len(slices4))
// 拷贝切片的值
copy(slices5, slices4)
// 修改切片
slices5[0] = 4
fmt.Println(slices4)
fmt.Println(slices5)

运行结果为

[1 2 3 4]
[4 2 3 4]

删除切片中的值

Go语言中并没有删除切片元素的专用方法,我们可以利用切片本身的特性来删除元素。代码如下

// 删除切片中的值
var slices6 = []int {0,1,2,3,4,5,6,7,8,9}
// 删除下标为1的值
slices6 = append(slices6[:1], slices6[2:]...)
fmt.Println(slices6)

运行结果

[0 2 3 4 5 6 7 8 9]

切片的排序算法以及sort包

编写一个简单的冒泡排序算法

func main() {
	var numSlice = []int{9,8,7,6,5,4}
	for i := 0; i < len(numSlice); i++ {
		flag := false
		for j := 0; j < len(numSlice) - i - 1; j++ {
			if numSlice[j] > numSlice[j+1] {
				var temp = numSlice[j+1]
				numSlice[j+1] = numSlice[j]
				numSlice[j] = temp
				flag = true
			}
		}
		if !flag {
			break
		}
	}
	fmt.Println(numSlice)
}

在来一个选择排序

// 编写选择排序
var numSlice2 = []int{9,8,7,6,5,4}
for i := 0; i < len(numSlice2); i++ {
    for j := i + 1; j < len(numSlice2); j++ {
        if numSlice2[i] > numSlice2[j] {
            var temp = numSlice2[i]
            numSlice2[i] = numSlice2[j]
            numSlice2[j] = temp
        }
    }
}
fmt.Println(numSlice2)

对于int、float64 和 string数组或是切片的排序,go分别提供了sort.Ints()、sort.Float64s() 和 sort.Strings()函数,默认都是从小到大进行排序

var numSlice2 = []int{9,8,7,6,5,4}
sort.Ints(numSlice2)
fmt.Println(numSlice2)

降序排列

Golang的sort包可以使用 sort.Reverse(slic e) 来调换slice.Interface.Less,也就是比较函数,所以int、float64 和 string的逆序排序函数可以这样写

// 逆序排列
var numSlice4 = []int{9,8,4,5,1,7}
sort.Sort(sort.Reverse(sort.IntSlice(numSlice4)))
fmt.Println(numSlice4)

标签:int,fmt,len,切片,var,Go,numSlice2
From: https://blog.csdn.net/weixin_72525373/article/details/144042326

相关文章

  • COMP4134 Algorithms and Data Structures
    ProjectinAdvancedAlgorithmsandDataStructuresCOMP4134UNNCOverviewForthisproject,youaretaskedwithsolvingareal-worldtransportationproblem.Formallyspeaking,itiscalledthepickupanddeliveryproblemwithtimewindows(PDPTW).Thepi......
  • Django框架--ORM操作
    1.查询操作1.1filter()用法:用于过滤查询结果,返回符合条件的记录。支持链式调用。示例:queryset=MyModel.objects.filter(field=value)SQL查询示例:SELECT*FROMMyModelWHEREfield=value;性能特点:根据过滤条件生成SQL查询。支持复杂查询条件,性能取决于查询条件和索引。1......
  • DJANGO进阶:信号机制
    django信号是一种机制,允许你在特定事件发生时(不需要再次修改"特定事件"的代码),执行另一部分的代码逻辑意义:类似于装饰器的作用,可以在不修改现有代码的逻辑下,触发自定义逻辑常见用途数据变更通知:当模型实例被创建、更新或删除时发送信号用户注册/登录:在用户注册或登录......
  • Django框架--中间件
    一、介绍1.中间件的定义Django中间件是一个轻量级、底层的“插件”系统,用于全局地修改Django的输入或输出。每个中间件组件可以对请求进行处理或对响应进行处理,或者同时处理二者。2.中间件的功能中间件可以执行的操作包括:请求预处理:在视图函数处理请求之前,执行一些前置操作(如......
  • 【速通GO】基础结构和语法
    独立站原文基础结构以及执行方式基础结构//包名packagemain//引入包import"fmt"//main函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有init()函数则会先执行该函数//注意{不能单独放在一行,否则在运行时会产生错误func......
  • Go语言基本数据类型和运算符
    1.Go语言基本数据类型和运算符Go语言是静态编程语言。在Go语言中,数据类型用于声明函数和变量。当编译器编译Go程序时,通过某个值的数据类型,编译器就能够知晓要为这个值分配多大内存。值被存储在指定大小的内存中后,就可以通过算术、关系、逻辑等运算符对其进行计算。1.1Go语言变......
  • OpenEuler安装MongoDB并配置访问密码
    1.下载MongoDB、安装wgethttps://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-4.4.18.tgztarzxvfmongodb-linux-x86_64-rhel80-4.4.18.tgz移动到/home路径下mvmongodb-linux-x86_64-rhel80-4.4.18/homecd/homemvmongodb-linux-x86_64-rhel80-4.4.1......
  • go-resty学习记录
    一.go-resty一个优秀的HTTP客户端库go-resty是一个优秀的HTTP客户端库,支持链式调用,超时控制,TLS,Cookie管理,链接池,代理,支持多种认证方式包括基本认证和OAuth2.0,支持发送JSON、XML和URL编码的数据,文件上传和下载,支持发送大量请求并批量处理响应结果,同时提供......
  • 你会PHP、JAVA、Python或GO吗?都有做过哪些应用呢?
    PHP、Java、Python和Go都是广泛应用的编程语言,它们各自在不同的领域和场景中发挥着重要的作用。以下是它们各自的一些典型应用:PHPPHP是一种流行的服务器端脚本语言,特别适用于Web开发。以下是PHP的一些主要应用:电商:PHP是亚马逊网站的服务器端语言,用于处理订单、客户管理和产品......
  • go泛型函数学习
    01什么是泛型泛型类似C++中的模板Go是一门强类型语言,意味着程序中的每个变量和值都有某种特定的类型,例如int、string等。在函数签名中,我们需要对参数和返回值指定类型,如下所示:funcAdd(a,bint)int参数a和b的类型是int,返回值类型也是int,结果是a和b的和。对两......