一文带你深入了解Go语言中切片的奥秘

目录
  • Go语言基础三
    • 切片的定义
    • 创建切片的方式
    • 切片初始化

Go语言基础三

切片的定义

1. 切片:切片是数组的一个引用,因此切片是引用类型。但自身是结构体,值拷贝传递。

2. 切片的长度可以改变,因此,切片是一个可变的数组。

3. 切片遍历方式和数组一样,可以用len()求长度。表示可用元素数量,读写操作不能超过该限制。

4. cap可以求出slice最大扩张容量,不能超出数组限制。0 <= len(slice) <= len(array),其中array是slice引用的数组。

5. 切片的定义:var 变量名 []类型,比如 var str []string  var arr []int。

6. 如果 slice == nil,那么 len、cap 结果都等于 0。

创建切片的方式

package main
​
import "fmt"
func main() {
   var s1 []int
   if s1 == nil {
      fmt.Println("是空")
   } else {
      fmt.Println("不是空")
   }
   s2 := []int{}
   var s3 []int = make([]int, 0)
   fmt.Println(s1, s2, s3)
   var s4 []int = make([]int, 0, 0)
   fmt.Println(s4)
   s5 := []int{1, 2, 3}
   fmt.Println(s5)
   arr := [5]int{1, 2, 3, 4, 5}
   var s6 []int
   s6 = arr[1:4]
   fmt.Println(s6)
}

我们首先定义了一个未进行初始化变量,名字为s1,数据类型为int类型的数组,同时运用if进行判断,由本题的demo可知,该答案为;接下来对s1、s2、s3这三个数组进行打印输出,由于三个数组均未进行初始化操作,因此三个数组打印出来的值都是[]s4数组也未进行初始化的操作,因此s4数组打印输出也是[];s5数组顾名思义,45 打印出来即为[1,2,3];我们对s6数组进行初始化操作,并且用arr数组的元素进行处理,使用切片的方法,对s6进行切片,最终打印出来的结果为[2,3,4]

切片初始化

package main
​
import (
    "fmt"
)
​
var arr = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var slice0 []int = arr[2:8]
var slice1 []int = arr[0:6]        //可以简写为 var slice []int = arr[:end]
var slice2 []int = arr[5:10]       //可以简写为 var slice[]int = arr[start:]
var slice3 []int = arr[0:len(arr)] //var slice []int = arr[:]
var slice4 = arr[:len(arr)-1]      //去掉切片的最后一个元素
func main() {
    fmt.Printf("全局变量:arr %v\n", arr)
    fmt.Printf("全局变量:slice0 %v\n", slice0)
    fmt.Printf("全局变量:slice1 %v\n", slice1)
    fmt.Printf("全局变量:slice2 %v\n", slice2)
    fmt.Printf("全局变量:slice3 %v\n", slice3)
    fmt.Printf("全局变量:slice4 %v\n", slice4)
    fmt.Printf("-----------------------------------\n")
    arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
    slice5 := arr[2:8]
    slice6 := arr[0:6]         //可以简写为 slice := arr[:end]
    slice7 := arr[5:10]        //可以简写为 slice := arr[start:]
    slice8 := arr[0:len(arr)]  //slice := arr[:]
    slice9 := arr[:len(arr)-1] //去掉切片的最后一个元素
    fmt.Printf("局部变量: arr2 %v\n", arr2)
    fmt.Printf("局部变量: slice5 %v\n", slice5)
    fmt.Printf("局部变量: slice6 %v\n", slice6)
    fmt.Printf("局部变量: slice7 %v\n", slice7)
    fmt.Printf("局部变量: slice8 %v\n", slice8)
    fmt.Printf("局部变量: slice9 %v\n", slice9)
}

首先我们根据代码要求定义四个数组,类型均为int类型,并对它们分别进行切片处理。我们在处理slice4数组的时候,做法是去掉切片的最后一个元素

上述运算结果显而易见,作者在这里不再进行阐述,如有不会的,可详细看数组的那一篇文章的讲解

package main
​
import (
    "fmt"
)
​
var slice0 []int = make([]int, 10)
var slice1 = make([]int, 10)
var slice2 = make([]int, 10, 10)
​
func main() {
    fmt.Printf("make全局slice0 :%v\n", slice0)
    fmt.Printf("make全局slice1 :%v\n", slice1)
    fmt.Printf("make全局slice2 :%v\n", slice2)
    fmt.Println("--------------------------------------")
    slice3 := make([]int, 10)
    slice4 := make([]int, 10)
    slice5 := make([]int, 10, 10)
    fmt.Printf("make局部slice3 :%v\n", slice3)
    fmt.Printf("make局部slice4 :%v\n", slice4)
    fmt.Printf("make局部slice5 :%v\n", slice5)
}

由于上述的全局变量和局部变量均未进行初始化的操作,因此数组的值全部为0

package main
​
import (
    "fmt"
)
​
func main() {
    data := [...]int{0, 1, 2, 3, 4, 5}
​
    s := data[2:4]
    s[0] += 100
    s[1] += 200
​
    fmt.Println(s)
    fmt.Println(data)
}

main函数中,我们定义了一个名为data,长度为任意类型,数据类型为int类型的数组,并进行初始化赋值的操作;使用变量s对数组data进行切片处理,同时秉持着包前不包后的语法规则,顾切片元素应为{2,3},在下一步的赋值操作里面,我们将2进行赋值操作(索引为0),得到的结果为102 ;同理,s[1]得到的值为203。紧接着最后一个打印输出大家也很清楚啦,就不作赘述了

package main
​
import "fmt"
​
func main() {
    s1 := []int{0, 1, 2, 3, 8: 100} // 通过初始化表达式构造,可使用索引号。
    fmt.Println(s1, len(s1), cap(s1))
​
    s2 := make([]int, 6, 8) // 使用 make 创建,指定 len 和 cap 值。
    fmt.Println(s2, len(s2), cap(s2))
​
    s3 := make([]int, 6) // 省略 cap,相当于 cap = len。
    fmt.Println(s3, len(s3), cap(s3))
}

由上方代码可知,我们定义了一个名为s1,数组长度为9,数据类型为int类型的数组。我们在调用函数打印输出的时候,由于数组中第9个元素被替换为100,所以最终的结果是[0 1 2 3 0 0 0 0 100] 9 9,后两个数组同理;值得一提的是,如果我们省略写cap,则默认为cap = len

package main
​
import "fmt"
​
func main() {
    s := []int{0, 1, 2, 3}
    p := &s[2] // *int, 获取底层数组元素指针。
    *p += 100
​
    fmt.Println(s)
}

我们定义了一个数组,里面存放了4个元素,接着我们使用&来获取底层数组元素指针,然后使其带有+100的操作,最终索引为3的元素就被赋值成了102,因此最后的结果是[0 1 102 3]

package main
​
import (
    "fmt"
)
​
func main() {
    d := [5]struct {
        x int
    }{}
​
    s := d[:]
​
    d[1].x = 10
    s[2].x = 20
​
    fmt.Println(d)
    fmt.Printf("%p, %p\n", &d, &d[0])
​
}

我们在main方法里面定义了一个函数体结构,在函数体里面定义了一个int类型的变量,名为x,紧接着我们将数组d拷贝到s中,同时将d数组中索引为1的元素赋值为10;同理,索引为2的元素赋值为20,因此打印的结果为[{0} {10} {20} {0} {0}],紧接着关于地址值的打印就不做赘述啦

到此这篇关于一文带你深入了解Go语言中切片的奥秘的文章就介绍到这了,更多相关Go语言切片内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Go数组与切片轻松掌握

    目录 数组(array) 初始化数组 数组赋值 遍历数组 数组对比 切片(slice) 切片的性质 切片初始化 切片赋值 切片的容量 append以及扩容 在 Go 中,数组和切片的功能其实是类似的,都是用来存储一种类型元素的集合.数组是固定长度的,而切片的长度是可以调整的 数组(array) 我们在声明一个数组的时候据必须要定义它的长度,并且不能修改. 数组的长度是其类型的一部分:比如,[2]int 和 [4]int 是两个不同的数组类型. 初始化数组 // 1. 创建一维数组 // 元素都是

  • Go slice切片使用示例详解

    目录 定义 定义并初始化 长度和容量 由数组得到切片 更多切割方式举例 切片的长度和容量 切片再切片 slice是引用类型 总结 定义 切片区别于数组,是引用类型, 不是值类型.数组是固定长度的,而切片长度是可变的,我的理解是:切片是对数组一个片段的引用. var s1 []int //定义一个存放int类型元素的切片 var s2 []string //定义一个存放string类型元素的切片 fmt.Println(s1, s2) fmt.Println(s1 == nil) //true 为

  • golang之数组切片的具体用法

    目录 数组 切片 切片的创建 直接声明 new方式初始化 字面量 make方式 截取方式 s[:] s[i:] s[:j] s[i:j] s[i:j:x] 看个例子 切片的扩容 内存对齐 空切片和nil切片 数组是值传递,切片是引用传递? 数组和slice能不能比较 只有长度相同,类型也相同的数组才能比较 slice只能和nil做比较,其余的都不能比较 数组 go开发者在日常的工作中slice算是用的比较多的了,在介绍slice之前,我们先了解下数组,数组相信大家都不陌生,数组的数据结构比较简单

  • golang切片原理详细解析

    目录 切片的解析 切片的初始化 字面量初始化 make初始化 切片的截取 切片的复制 切片的扩容 总结 切片的解析 当我们的代码敲下[]时,便会被go编译器解析为抽象语法树上的切片节点, 被初始化为切片表达式SliceType: // go/src/cmd/compile/internal/syntax/parser.go // TypeSpec = identifier [ TypeParams ] [ "=" ] Type . func (p *parser) typeDecl(g

  • GoLang切片相关问题梳理讲解

    目录 1.数组和切片有什么区别 2.拷贝大切片一定比拷贝小切片代价大吗 3.切片的深浅拷贝 4.零切片 空切片 nil切片是什么 4.1零切片 4.2nil切片 4.3空切片 5.切片的扩容策略 1.17之前 1.18之后 6. 参数传递切片和切片指针有什么区别 7.range遍历切片有什么要注意的 1.数组和切片有什么区别 Go语言中数组是固定长度的,不能动态扩容,在编译期就会确定大小,声明方式如下: var buffer [255]int buffer := [255]int{0} 切片是对

  • 一文带你深入了解Go语言中切片的奥秘

    目录 Go语言基础三 切片的定义 创建切片的方式 切片初始化 Go语言基础三 切片的定义 1. 切片:切片是数组的一个引用,因此切片是引用类型.但自身是结构体,值拷贝传递. 2. 切片的长度可以改变,因此,切片是一个可变的数组. 3. 切片遍历方式和数组一样,可以用len()求长度.表示可用元素数量,读写操作不能超过该限制. 4. cap可以求出slice最大扩张容量,不能超出数组限制.0 <= len(slice) <= len(array),其中array是slice引用的数组. 5. 切

  • 一文带你轻松学会Go语言动态调用函数

    目录 前言 JavaScript 动态调用函数 Go 中动态调用方法 前言 经常在开发的时候会遇到这样的场景,几个模块的都有相同的方法,但会因为不同的类型的需要调用不同模块的方法.使用一个 switch 可以很方便的解决问题.但是当你遇到的场景是几个模块的方法都是需要的执行,同时它需要在不同的配置下执行相对应的方法. func m1(){} func m2(){} func m3(){} c := cron.New(cron.WithSeconds()) c.addFunc(config1,fu

  • 一文带你搞懂C语言动态内存管理

    目录 一.malloc函数和free函数 二.calloc函数与malloc函数的异同 三.柔性数组 一.malloc函数和free函数 (1) 这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针. 如果开辟成功,则返回一个指向开辟好空间的指针. 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查. 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定. 如果参数 size为0,malloc的行为是标准是未

  • 一文带你搞懂C语言预处理宏定义

    目录 预定义符号 #define #define 定义标识符 #define 定义宏 替换规则 # 和## 预定义符号 这些预定义符号都是语言内置的 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义 VS环境下未定义__STDC__ ,说明Visual Studio并未完全遵循ANSI C. #define #defi

  • 一文带你彻底搞懂Docker中的cgroup的具体使用

    目录 什么是cgroup cgroup的组成 cgroup提供的功能 限制cgroup中的CPU 限制cgroup中的内存 限制cgoup的进程数 前言 进程在系统中使用CPU.内存.磁盘等计算资源或者存储资源还是比较随心所欲的,我们希望对进程资源利用进行限制,对进程资源的使用进行追踪.这就让cgroup的出现成为了可能,它用来统一将进程进行分组,并在分组的基础上对进程进行监控和资源控制管理. 什么是cgroup Linux CGroup(Linux Contral Group),它其实是Lin

  • 十个示例带你深入了解Go语言中的接口

    1.空接口既然可以存储任意类型的值,那么从空接口获取到的值是否可以直接使用?看下面栗子 package main import (  "fmt" ) var a interface{} var b interface{} func main() {  a = 1024  b = 100  res := a + b  fmt.Println(res) } 报错: invalid operation: operator + not defined on a (variable of typ

  • go语言中切片的长度和容量的区别

    切片的长度,显而易见的就是元素的个数,根据元素的个数进行返回具体的长度. 切片的长度,更像是一个警戒值,如果长度与容量相等,就会进行容量的扩容,比如 des :=make([]int , 3 , 5) //此时,长度为3,容量为5,但是如果使用append(), //切片长度会变为4,再次使用append()切片长度变为5. //此时,切片长度与容量相同,此时,切片的容量增大变为cap = len*2 也就是通过一个容量设警戒值,如果等于警戒值,就会自动将切片进行扩容 补充:Go语言中切片的长度

  • go语言中切片Slice与数组Array对比以及panic: runtime error: index out of range问题解决

    目录 前言 一.go slice是什么 二.go slice实战案例 1.slice创建.使用 2.slice的长度和容量概念理解 3. 切片扩容及slice panic: runtime error: index out of range 附:go 判断数组下标是否存在 总结 前言 在go语言的学习历程当中,slice数据类型引起了我的好奇心.为啥不直接使用Slice,是人性的扭曲还是道德的沦丧~,下面让我们一探究竟~~ 一.go slice是什么 go语言中的slice是一个基于Array封

  • 详解Go语言中切片的长度与容量的区别

    目录 切片的声明 切片的长度和容量 切片追加元素后长度和容量的变化 append 函数 切片的源代码学习 切片的结构体 切片的扩容 总结 切片的声明 切片可以看成是数组的引用(实际上切片的底层数据结构确实是数组).在 Go 中,每个数组的大小是固定的,不能随意改变大小,切片可以为数组提供动态增长和缩小的需求,但其本身并不存储任何数据. // 数组的声明 var a [5]int //只指定长度,元素初始化为默认值0 var a [5]int{1,2,3,4,5} // 切片的声明 // 方法1:

  • Go语言中切片使用的注意事项小结

    前言 Go 语言中的slice类型可以理解为是数组array类型的描述符,包含了三个因素: 指向底层数组的指针 slice目前使用到的底层数组的元素个数,即长度 底层数组的最大长度,即容量 因此当我们定义一个切片变量,s := make([]int, 5, 10),即为指向了一个最大长度为10的底层数组,目前切片s使用到的长度为5. 在使用切片的时候,有几个注意事项,下面来一起看看吧. 使用append 先看一个例子: // 创建一个整型切片 // 其长度和容量都是 5 个元素 slice :=

随机推荐