Go 复合类型之切片类型 一、引入 我们在上一个节Go复合类型之数组类型提到过,数组作为最基本同构类型在 Go 语言中被保留了下来,但数组在使用上确有两点不足:固定的元素个数,以及传值机制下导致的开销较大 这种方式被称为数组的切片化,比如下面代码: arr := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} sl := arr[3:7:9] fmt.Println(" arr:", arr) //arr: [1 2 3 4 5 6 7 8 9 10] fmt.Println("s1:", sl) //s1: [4 5 6 7] 我们基于数组 arr 创建了一个切片 7] } 注意:通过var声明的零值切片可以在append()函数直接使用,无需初始化。 需要注意的是,切片扩容还会根据切片中元素的类型不同而做不同的处理,比如int和string类型的处理方式就不一样。
1.切片转换 日常开发我们可能需要一个类型的切片转换为另一个类型的切片。 比如 int[] 转为 []string。 如果为多种不同类型切片互转都实现各自的转换函数,无疑是低效繁琐的。 2.反射 实际上,利用 Golang 反射,可以为目标类型切片的转换只写一个函数。 比如,可以接收任意类型切片,将其转换为 []string。 反射涉及到运行时类型的判断,有一定性能开销,性能会降低 20% 左右。 如果转换为不同的目标类型切片,仍需要编写多个不同的转换函数。 3.泛型 Golang 在 1.18 中引入了泛型。 利用泛型,我们可以不用针对不同的目标类型切片单独实现转换函数,真正做到一个函数,完成所有类型切片间的转换。
1、切片介绍 2、声明和初始化 2.1 make创建 2.2 字面量创建 2.3 创建数组和切片的区别 2.4 创建切片的本质 3、切片访问 4、nil和空切片 5、切片中添加元素 6、通过切片创建切片 7、切片遍历 8、切片拷贝 9、切片作为函数参数 1、切片介绍 Go中的切片slice依赖于数组,它的底层就是数组,所以数组具有的优点,slice都有。 即底层数组的长度,表示这个slice目前最多能扩展到的长度 长度(length):表示slice当前的长度,即当前容纳的元素个数 数组指针(array):指向底层数组的指针 比如创建一个长度为3,容量为5,int类型的切片 ,一个是引用类型一个是值类型 2.4 创建切片的本质 切片相关源码放置位置: src/runtime/slice.go, 我们使用make时, 实际上是调用的makeslice函数 // 这里一波操作过后返回的是 ,如果要修改请使用后面的深拷贝复制一个全新的切片 7、切片遍历 切片是一个集合,可以迭代其中的元素。
切片slice 切片是引用类型切片初始化之后才能进行使用 切片不能直接比较 append函数可以向切片中追加元素,同时还能利用append函数删除切片中的某个元素 切片是数组的底层封装 make([]T , len,map)函数能够直接创建切片make([]int, 5, 10) 切片(Slice)是一个拥有相同类型元素的可变长度的序列。 切片是引用类型,必须初始化才能进行使用。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。 切片是一个引用类型,一般用于快速地操作一块数据集合。 ,不支持直接比较,只能和nil比较 } GO切片 make函数 通过make()函数构造动态的切片,基本语法为 make([]T, size, cap) T:切片的元素类型 size:切片中元素的数量 cap:8 ptr:0xc00000c280 [0 1 2 3 4 5 6 7] len:8 cap:8 ptr:0xc00000c280 [0 1 2 3 4 5 6 7 8] len:9 cap:16
python有哪些切片类型 1、list切片,如果第一个索引是0,还可以省略。 tuple也是一种list,唯一区别是tuple不可变,也可以用切片操作。操作的结果仍是tuple。 字符串'xxx'也可以看成是一种list,每个元素就是一个字符,字符串也可以用切片操作。 >>> 'ABCDEFG'[:3] 'ABC' >>> 'ABCDEFG'[::2] 'ACEG' 以上就是python的3种切片类型,希望对大家有所帮助。 更多Python学习指路:python基础教程 本文教程操作环境:windows7系统、Python 3.9.1,DELL G3电脑。
NumPy 数组切片NumPy 数组切片用于从数组中提取子集。它类似于 Python 中的列表切片,但支持多维数组。一维数组切片要从一维数组中提取子集,可以使用方括号 [] 并指定切片。 示例:import numpy as np# 创建一维数组arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])# 从第二个元素到第五个元素(不包括)print( print(arr[-3:-1]) # 输出:array([8, 9])二维数组切片要从二维数组中提取子集,可以使用逗号分隔的两个索引,每个索引表示相应维度的切片。 示例:import numpy as np# 创建二维数组arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])# 从第二行到第三行,第一列到第三列(不包括) 一个包含 7 个复杂数的数组。一个包含 10 个日期时间对象的数组。在评论中分享您的代码和输出。
类型表示法 对于一个元素类型为T的切片类型来说,它的类型字面量就是: []T 可以看出,长度并不是切片类型的一部分(即它不会出现在表示切片类型的类型字面量中)。另外,切片的长度是可变的。 相同类型的切片值可能会有不同的长度。 切片类型声明中的元素类型也可以是任意一个有效的 Go 语言数据类型。例如: []rune 如上用于表示元素类型为 rune 的切片类型。 "", 2: "Swift", 3: "Java", 4: "C", 5: "C++", 6: "PHP", 7: "", 8: "Go"} 3. 切片值的底层数据结构: 一个切片值的底层数据结构包含了一个指向底层数组的指针类型值,一个代表了切片长度的 int 类型值和一个代表了切片容量的 int 类型值。 var array2 [10]int = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} slice5 := array2[2:6] 如上我们可以直接访问和修改 array2
[]interface{} 表示,但不能表示任意切片类型,即具体类型的切片无法转换为 []interface{} ,需要显示转换。 fmt.Println("fib =",fib) } 输出结果: fib = [1] 注意,[]interface{} 表示存放任意类型元素的切片,并不是任意切片类型,所以使用具体类型的切片时 ,需要显示地将具体类型的切片转换为 []interface{},然后再将结果 []interface{} 切片转换回具体类型的切片。 我们使用 interface{} 接收任意切片类型,利用 Go 提供的反射功能,实现对任意切片类型的插入操作。 主要有如下步骤: (1)将任意切片类型转换为[]interface{}; (2)对[]interface{}进行插入; (3)将结果[]interface{}切片转换为具体类型的切片。
,还可以是某个类型的指针 new函数返回一个TYPE类型的数据结构划分内存并执行默认的初始化操作,然后返回这个数据对象的指针 只声明不初始化,必须用new, 两个数组指针直接复制 package main 切片是围绕动态数据来构建的 数组一旦创建就不能更改长度,但是切片可以按需求自动增长和缩小 增长是使用内置的append函数来实现的 缩小通过对切片的再次切片来实现 声明和初始化 var直接声明 对比表格 函数名 适用范围 返回值 填充值 new new可以对所有类型进行内存分配 new返回指针 new填充零值 make make只能创建类型(slice、map、channel) make返回引用 make填充非零值 通过切片创建新的切片 语法如下 slice[start:end:cap] 其中start表示从slice的第几个元素开始 end控制切片的长度(end-i) cap控制切片的容量 ,如果没有给定cap,slice的长度值,则表示到底层数组的最尾部 新切片的长度 = end-start 新切片的容量 = cap-start
我们知道使用分片可以获取列表的部分元素,那么如何使用切片获取产生器类型对象中的部分元素呢?
数组 数组有两个特点: 固定长度 元素类型相同 正是因为其长度固定,所以相比于切片,在开发过程中用的是比较少的。但数组是切片的基础,理解了数组,再学习切片就容易多了。 创建切片 创建切片有两种方式: 第一种方式是基于数组创建: // 基于数组创建切片 var array = [...]int{1, 2, 3, 4, 5, 6, 7, 8} s1 := array[3 11) fmt.Printf("s6: %v\n", s6) // s5: [1 2 3 4 5 6 7 8 10 11] 追加另一个切片,需要在另一个切片后面跟三个点。 // 追加另一个切片 s7 := []int{12, 13} s7 = append(s7, s6...) fmt.Printf("s7: %v\n", s7) // s7: [12 13 1 2 3 总结 本文学习了复合数据类型的前两种:数组和切片。分别介绍了它们的创建,常用操作,以及函数间的传递。 数组长度固定,是切片的基础;切片长度可变,多一个容量属性,其指针指向的底层结构就是数组。
如果你还分不清切片和数组的区别,就仔细阅读下这篇文章吧,我尽力给你讲清楚。 一、Go 里面基础类型只有数组 第一个坑点,就是很多人会把切片混入到 Go 的基础类型里面,这是一个最大的坑。 那切片到底是什么呢? 这可能是创始人,某一时刻脑袋一发光,发现让开发者直接操作数组,总是容易出错。 于是就帮我们写了一个功能扩展,取了一个名字就叫切片。 所以切片只是一个功能扩展,是一个结构体。 会自动计算数组长度 fmt.Println(a) fmt.Printf("%T",a) 他会自动计算长度,你打印类型时得到的是这样的: [1 2 3] [3]int 一不小心变切片: 如果你一不小心忘记前面加长度了 三、典型坑 1、长度坑 细心的同学会发现,不同长度的数组打印出来的类型是不一样的。 所以一般在传递数组或者切片时,我们为了节省性能一般都传递指针。 最后,再次强调,Go 的基础数据类型里面是没有切片的,理解了么? 你学废了么?
在gocron.go文件的main函数中,有下面这一句,从这句代码中可以学习到切片和类型的综合运用 cliApp.Flags = append(cliApp.Flags, []cli.Flag{}... 首先在go语言中定义一个类型需要使用type 名字 struct{},还可以给这个类型定义成员方法 type Taoshihan struct { } func (t Taoshihan) Say() string { return "my name is taoshihan" } 这里我就定义了Taoshihan类型,为他增加了Say方法 实例化这个类型需要 名字{},下面这个就是实例化了一个 Taoshihan对象 mytao := Taoshihan{} 切片可以看成是一个可变长度的数组,声明定义一个切片可以向下面这样 var 名字 []存储的类型 var myslice []Taoshihan 我这个切片中存的是Taoshihan这个类型 往切片中添加数据需要使用append函数,下面我往切片中增加了两个数据 myslice=append(myslice,mytao,Taoshihan{}
含义 切片是一个种特殊的数组。是对数组的一个连续片段的引用,所以切片是一个引用类型。切片可以是数组中的一部分,也可以是由起始和终止索引标识的一些项的子集。 [0:0]) // 打印结果为 切片: [] 直接声明切片 除了可以从原有的数组或者切片中生成切片外,也可以声明一个新的切片,每一种类型都可以拥有其切片类型,表示多个相同类型元素的连续集合,因此切片类型也可以被声明 例如上面的slince1定义的时2个长度,但是只给下标为0的分配了值,因此下标为1的根据数据类型时string类型,默认分配一个" "值。 常用操作 长度计算 切片长度使用len()计算。 = append(slice, 6,7,8,9) fmt.Println(slice) // 打印新的切片的长度和容量 fmt.Println("新切片长度和容量分别是", len(slice), cap(slice)) // 打印的内容分别如下 原始切片长度和容量分别是 3 3 [1 2 3 1] [1 2 3 1 6 7 8 9] 新切片长度和容量分别是 8 12 注意事项 1.在切片的尾部添加元素
#切片 #切片指从现有列表中,获取一个子列表 #创建一个列表,一般创建列表时,变量的名字会使用复数 stus = ['孙悟空','猪八戒','沙和尚'] #列表的索引可以是负数,如果索引是负数,则从后向前获取元素 print(stus[-1]) #通过切片来获取指定的元素 #语法:列表[起始:结束],通过切片获取元素时,会包括起始位置的元素,不会包括结束位置的元素 #做切片操作时,总会返回一个新的列表,不会影响原来的列表 #切片的起始位置和结束位置的索引都可以省略不写 #如果省略结束位置,则会一直截取到最后,如果省略开始位置,则会从第一个元素开始截取 print(stus[1:]) print(stus[:2]) print
Object.getOwnPropertyNames(Promise); // (7) ["length", "name", "prototype", "all", "race", "resolve", "reject"] 发现一共有7个属性和方法。 { // 未被调用 }, function(error) { console.log(error); // 堆栈跟踪 /* Error: fail at <anonymous>:7: 如果该值是一个Promise对象,则直接返回该对象;如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定;否则的话(该value为空,基本类型或者不带 promise Promise.resolve(thenable); 返回一个最终状态由then方法执行决定的Promise对象 Promise.resolve(value) value为空,基本类型
} fmt.Println(b.Name) 定义一个接口,接口里面有一个成员方法 type Flag interface { GetName() string } 定义另一个类型 ,这个类型刚好就有这个方法,那么就可以认为这个类型实现了接口 type StringFlag struct { } func (t StringFlag) GetName() string { return "taoshihan" } 这个时候如果定义Flag类型的变量,那么StringFlag也能被赋值过去 var a Flag a = StringFlag{} a.GetName() 再回到原代码中的逻辑
3.6 数组、向量和切片 Rust 用 3 种类型来表示内存中的值序列。 类型 [T; N] 表示 N 个值的数组,每个值的类型为 T。 笔记 类型 Vec<T> 类似于 JavaScript 中的数组 [],在日常开发中使用频率很高 类型 &[T] 和 &mut [T] 可称为 T 的共享切片和 T 的可变切片,它们是对一系列元素的引用 (lazy_caterer[3], 7); assert_eq! [2, 3, 5, 7]; assert_eq! 尝试借用超出数据末尾的切片会导致 panic。 由于切片几乎总是出现在引用符号之后,因此通常只将 &[T] 或 &str 之类的类型称为“切片”,使用较短的名称来表示更常见的概念。
的 序列 数据容器 , 因此 都可以进行 切片操作 ; 由于 元组 和 字符串 都是 不可更改的 数据容器 , 因此 序列切片操作 , 不会影响原来的序列 , 而是得到一个新的序列 ; 序列切片语法 1、代码示例 - 省略 起始坐标 / 结束坐标 / 步长 代码示例 : """ 序列切片 代码示例 """ # 列表 切片 my_list = [0, 1, 2, 3, 4, 5] # I. 对 字符串 str 切片 my_str = "123456789" # 字符串切片 从头到尾 步长 2 slice = my_str[::2] print(slice) # 13579 执行结果 : 13579 3、代码示例 - 步长为 -1 的切片 如果步长设置为 -1 , 则从后向前进行切片 ; 如果步长为负数 , 其起始下标索引 要 大于 结束下标索引 ; 代码示例 : # III. 、代码示例 - 完整版 代码示例 : """ 序列切片 代码示例 """ # 列表 切片 my_list = [0, 1, 2, 3, 4, 5] # I.
【从零开始学习Go语言】Go语言的数组与切片引用类型与值类型 一.数组 二.多维数组 三.切片 四.值类型与引用类型 ---- 一.数组 go语言的数组在之前的一些例子中有引用过,go的数组在创建时需要声明存储数据的类型 数组的长度是固定且不课修改的,而切片的表达方式与数组基本一样,但大小不做限制,类似python中的数组 package main import ( "fmt" ) func main() { arr := []int{1, 2, 3, 4, 5, 6} fmt.Println(arr) } 不填写长度就是切片啦,不过这里注意一点,切片的长度第一次初始化是根据所传入参数长度确认,第二次是根据第一次传入的参数长度为基准 ,go会根据这个切片的原始长度叠加,假如第二次添加的数据没有达到12,它是不会再次叠加的 } ---- 四.值类型与引用类型 这里用一个例子来介绍吧: package main import ( " fmt" ) func main() { //值类型 fmt.Println("\n---------------值类型-------------------------") arr := [.