100天精通Golang(基础入门篇)——第11天:深入解析Go语言中的切片(Slice)及常用函数应用

news2024/11/15 22:22:16

在这里插入图片描述

🌷 博主 libin9iOak带您 Go to Golang Language.✨
🦄 个人主页——libin9iOak的博客🎐
🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐
🪁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🐥

100天精通Golang(基础入门篇)

  • 摘要:
  • 前言:
  • 100天精通Golang(基础入门篇)——第11天:深入解析Go语言中的切片(Slice)及常用函数应用
  • 一、切片(Slice)
    • 1.1 什么是切片?
    • 1.2 切片的语法
    • 1.3 修改切片
    • 1.4 len() 和 cap() 函数
    • 1.5 append() 和 copy() 函数
      • append()函数
      • copy() 函数
    • 代码案例总结
      • 代码案例1
      • 代码案例2:
      • 代码案例3:
      • 代码案例4:
      • 代码案例5:
    • 今日学习总结:
  • 结语

摘要:

本文是《100天精通Golang(基础入门篇)——第11天:切片(Slice)》,将详细介绍切片的概念、语法、修改、以及len()、cap()、append()和copy()函数的使用。读者将通过学习本文深入了解Golang中切片的使用方法和常用函数的功能。

前言:

切片(Slice)是Golang中非常重要的数据结构,它可以动态地调整大小,并且常用于处理集合的情况。在本文中,我们将系统地介绍切片的概念、语法和修改方式,并逐一讲解len()、cap()、append()和copy()函数的用法。通过学习本文,读者将更加熟悉切片的操作,提高对Golang的掌握程度。

100天精通Golang(基础入门篇)——第11天:深入解析Go语言中的切片(Slice)及常用函数应用

一、切片(Slice)

在Golang中,切片(Slice)是一种灵活、动态大小的数据结构,能够方便地处理集合类型的数据。通过切片,我们可以轻松地操作数组或其他切片,实现对数据的增删改查等操作。

1.1 什么是切片?

Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大切片是一种方便、灵活且强大的包装器。切片本身没有任何数据。它们只是对现有数组的引用。

切片与数组相比,不需要设定长度,在[]中不用设定值,相对来说比较自由

从概念上面来说slice像一个结构体,这个结构体包含了三个元素:

  1. 指针,指向数组中slice指定的开始位置
  2. 长度,即slice的长度
  3. 最大长度,也就是slice开始位置到数组的最后位置的长度

小结: 切片可以理解为对数组的一个引用,它由指向数组的指针、切片的长度和切片的容量组成。切片的长度表示切片中实际存储的元素个数,而容量表示切片底层数组的大小。切片相比于数组的优势在于它的大小是动态可变的,可以根据需要进行扩容或缩减。

1.2 切片的语法

在Golang中,切片的语法很简洁,使用方括号[ ]来声明一个切片,并指定切片的长度或容量。例如:

var slice []int             // 声明一个切片
slice := make([]int, 0)     // 创建一个切片,并指定长度为0

通过索引访问切片中的元素与数组类似,但切片可以动态地调整大小。

定义切片

var identifier []type

切片不需要说明长度。
或使用make()函数来创建切片:

var slice1 []type = make([]type, len)
也可以简写为
slice1 := make([]type, len)
make([]T, length, capacity)

初始化

s[0] = 1
s[1] = 2
s[2] = 3
s :=[] int {1,2,3 } 
s := arr[startIndex:endIndex] 

将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片(前闭后开),长度为endIndex-startIndex

s := arr[startIndex:] 

缺省endIndex时将表示一直到arr的最后一个元素

s := arr[:endIndex] 

缺省startIndex时将表示从arr的第一个元素开始

package main

import (  
    "fmt"
)

func main() {  
    a := [5]int{76, 77, 78, 79, 80}
    var b []int = a[1:4] //creates a slice from a[1] to a[3]
    fmt.Println(b)
}

1.3 修改切片

对切片进行修改非常方便,可以通过索引进行赋值或修改现有元素的值。此外,还可以使用切片作为参数传递给某个函数,并在函数内部对切片进行修改。这种特性使得切片在处理大量数据时非常高效。

slice没有自己的任何数据。它只是底层数组的一个表示。对slice所做的任何修改都将反映在底层数组中。

示例代码:

package main

import (  
    "fmt"
)

func main() {  
    darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
    dslice := darr[2:5]
    fmt.Println("array before",darr)
    for i := range dslice {
        dslice[i]++
    }
    fmt.Println("array after",darr) 
}

运行结果:

array before [57 89 90 82 100 78 67 69 59]  
array after [57 89 91 83 101 78 67 69 59]  

当多个片共享相同的底层数组时,每个元素所做的更改将在数组中反映出来。

示例代码:

package main

import (  
    "fmt"
)

func main() {  
    numa := [3]int{78, 79 ,80}
    nums1 := numa[:] //creates a slice which contains all elements of the array
    nums2 := numa[:]
    fmt.Println("array before change 1",numa)
    nums1[0] = 100
    fmt.Println("array after modification to slice nums1", numa)
    nums2[1] = 101
    fmt.Println("array after modification to slice nums2", numa)
}

运行结果:

array before change 1 [78 79 80]  
array after modification to slice nums1 [100 79 80]  
array after modification to slice nums2 [100 101 80]  

1.4 len() 和 cap() 函数

Golang提供了两个内置函数len()和cap()来获取切片的长度和容量。len()函数返回切片中实际存储的元素个数,而cap()函数返回切片底层数组的大小。这两个函数的使用非常简单,直接对切片调用即可。

切片的长度是切片中元素的数量。切片的容量是从创建切片的索引开始的底层数组中元素的数量。

切片是可索引的,并且可以由 len() 方法获取长度
切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少

package main

import "fmt"

func main() {
   var numbers = make([]int,3,5)

   printSlice(numbers)
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

运行结果

len=3 cap=5 slice=[0 0 0]

空切片

一个切片在未初始化之前默认为 nil,长度为 0

package main

import "fmt"

func main() {
   var numbers []int

   printSlice(numbers)

   if(numbers == nil){
      fmt.Printf("切片是空的")
   }
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

运行结果

len=0 cap=0 slice=[]
切片是空的
package main

import "fmt"

func main() {
   /* 创建切片 */
   numbers := []int{0,1,2,3,4,5,6,7,8}   
   printSlice(numbers)

   /* 打印原始切片 */
   fmt.Println("numbers ==", numbers)

   /* 打印子切片从索引1(包含) 到索引4(不包含)*/
   fmt.Println("numbers[1:4] ==", numbers[1:4])

   /* 默认下限为 0*/
   fmt.Println("numbers[:3] ==", numbers[:3])

   /* 默认上限为 len(s)*/
   fmt.Println("numbers[4:] ==", numbers[4:])

   numbers1 := make([]int,0,5)
   printSlice(numbers1)

   /* 打印子切片从索引  0(包含) 到索引 2(不包含) */
   number2 := numbers[:2]
   printSlice(number2)

   /* 打印子切片从索引 2(包含) 到索引 5(不包含) */
   number3 := numbers[2:5]
   printSlice(number3)

}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

运行结果

len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
len=0 cap=5 slice=[]
len=2 cap=9 slice=[0 1]
len=3 cap=7 slice=[2 3 4]

小结:

len()函数返回切片中实际存储的元素个数。也就是说,它告诉我们这个切片中有多少个元素。比如,如果我们有一个切片slice,那么通过len(slice)就可以得到它的长度。这对于我们在遍历切片或进行其他操作时非常有用。

cap()函数则返回切片底层数组的大小,也就是切片的容量。容量是指切片底层数组的总大小,而实际存储的元素个数可能小于或等于容量。因此,当我们使用append()函数向切片中添加元素时,如果超出了切片的容量,则底层数组会自动进行扩容。此时,我们就可以通过cap()函数来查看切片的容量是否发生了改变。

使用这两个函数可以帮助我们更好地了解和管理切片的大小和容量。比如,我们可以使用len()函数来判断切片是否为空,即长度为0;使用cap()函数可以了解切片当前的容量是否满足需求,是否需要进行扩容操作。

需要注意的是,len()和cap()函数只能用于切片和数组,并且只能对第一维度的长度和容量进行计算。如果我们有一个切片的切片,那么len()函数将返回第一维度的长度,而不会返回第二维度的长度。

总之,len()函数和cap()函数是Golang提供的两个非常有用的函数,它们可以帮助我们更好地了解和管理切片的大小和容量。在切片的使用过程中,记得经常使用它们,以便更好地利用切片的特性。

1.5 append() 和 copy() 函数

append()函数用于向切片中添加元素,可以一次添加一个或多个元素。如果切片的容量不足以容纳新添加的元素,append()函数会自动进行扩容操作。

append()函数

用于向切片中添加元素。它的功能非常强大,可以一次添加一个或多个元素。append()函数接受两个参数:第一个参数是要添加元素的切片,第二个参数是要添加的元素。添加完元素后,append()函数会返回一个新的切片,我们通常需要将其赋值给原始的切片。

除了添加元素,append()函数还有一个重要的功能——动态扩容。当切片的容量不足以容纳新添加的元素时,append()函数会自动进行扩容操作。它会创建一个新的底层数组,并将原始数据复制到新数组中。然后,它会将新添加的元素放入新数组中,并返回一个新的切片。这样,我们就可以使用扩容后的切片了。

需要注意的是,由于append()函数会创建一个新的底层数组并进行数据复制,因此在大量使用append()函数时,可能会带来一些性能开销。所以,在预知切片大小的情况下,最好提前指定好切片的容量,以减少扩容的次数。

copy() 函数

copy()函数用于将一个切片的内容复制到另一个切片中。这对于切片的复制和拷贝操作非常方便。copy()函数接受两个参数:第一个参数是目标切片,第二个参数是源切片。copy()函数会将源切片中的元素复制到目标切片中,并返回复制的元素个数。

与append()函数不同,copy()函数不会进行扩容操作。它仅将源切片中的元素按照顺序复制到目标切片中。因此,需要注意两个切片的大小要一致,否则可能会造成数据丢失或越界访问。

需要特别注意的是,在使用copy()函数时,切片的容量不会发生改变。目标切片的容量还是保持不变,因此,如果目标切片容量不足以容纳源切片,可能会导致部分数据丢失。

演示案例:

copy()函数用于将一个切片的内容复制到另一个切片中,非常方便实现切片的复制和拷贝操作。

append 向slice里面追加一个或者多个元素,然后返回一个和slice一样类型的slice
copy 函数copy从源slice的src中复制元素到目标dst,并且返回复制的元素的个数

append函数会改变slice所引用的数组的内容,从而影响到引用同一数组的其它slice。 但当slice中没有剩
余空间(即(cap-len) == 0)时,此时将动态分配新的数组空间。返回的slice数组指针将指向这个空间,而原
数组的内容将保持不变;其它引用此数组的slice则不受影响

下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)

   /* 允许追加空切片 */
   numbers = append(numbers, 0)
   printSlice(numbers)

   /* 向切片添加一个元素 */
   numbers = append(numbers, 1)
   printSlice(numbers)

   /* 同时添加多个元素 */
   numbers = append(numbers, 2,3,4)
   printSlice(numbers)

   /* 创建切片 numbers1 是之前切片的两倍容量*/
   numbers1 := make([]int, len(numbers), (cap(numbers))*2)

   /* 拷贝 numbers 的内容到 numbers1 */
   copy(numbers1,numbers)
   printSlice(numbers1)   
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

运行结果

len=0 cap=0 slice=[]
len=1 cap=2 slice=[0]
len=2 cap=2 slice=[0 1]
len=5 cap=8 slice=[0 1 2 3 4]
len=5 cap=12 slice=[0 1 2 3 4]

numbers1与numbers两者不存在联系,numbers发生变化时,numbers1是不会随着变化的。也就是说copy方法是不会建立两个切片的联系的

代码案例总结

代码案例1

package main

import "fmt"

func main() {
	/*
		数组array:
			存储一组相同数据类型的数据结构。
				特点:定长

		切片slice:
			同数组类似,也叫做变长数组或者动态数组。
				特点:变长

			是一个引用类型的容器,指向了一个底层数组。

		make()
			func make(t Type, size ...IntegerType) Type

			第一个参数:类型
				slice,map,chan
			第二个参数:长度len
				实际存储元素的数量
			第三个参数:容量cap
				最多能够存储的元素的数量


		append(),专门用于向切片的尾部追加元素
			slice = append(slice, elem1, elem2)
			slice = append(slice, anotherSlice...)
	*/
	//1.数组
	arr := [4]int{1, 2, 3, 4} //定长
	fmt.Println(arr)

	//2.切片
	var s1 []int
	fmt.Println(s1)

	s2 := []int{1, 2, 3, 4} //变长
	fmt.Println(s2)
	fmt.Printf("%T,%T\n", arr, s2) //[4]int,[]int

	s3 := make([]int, 3, 8)
	fmt.Println(s3)
	fmt.Printf("容量:%d,长度:%d\n", cap(s3), len(s3))
	s3[0] = 1
	s3[1] = 2
	s3[2] = 3
	fmt.Println(s3)
	//fmt.Println(s3[3]) //panic: runtime error: index out of range

	//append()
	s4 := make([]int, 0, 5)
	fmt.Println(s4)
	s4 = append(s4, 1, 2)
	fmt.Println(s4)
	s4 = append(s4, 3, 4, 5, 6, 7)
	fmt.Println(s4)

	s4 = append(s4, s3...)
	fmt.Println(s4)

	//遍历切片
	for i := 0; i < len(s4); i++ {
		fmt.Println(s4[i])
	}

	for i, v := range s4 {
		fmt.Printf("%d-->%d\n", i, v)
	}

}


运行结果:

GOROOT=D:\Go #gosetup
GOPATH=C:\Users\DELL\go #gosetup
D:\Go\bin\go.exe build -o C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice.exe Day11-Slice #gosetup
C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice.exe
[1 2 3 4]
[]
[1 2 3 4]
[4]int,[]int
[0 0 0]
容量:8,长度:3
[1 2 3]
[]
[1 2]
[1 2 3 4 5 6 7]
[1 2 3 4 5 6 7 1 2 3]
1
2
3
4
5
6
7
1
2
3
0-->1
1-->2
2-->3
3-->4
4-->5
5-->6
6-->7
7-->1
8-->2
9-->3

进程 已完成,退出代码为 0




运行截图:

在这里插入图片描述

代码案例2:


package main

import "fmt"

func main() {
	/*
		切片Slice:
			1.每一个切片引用了一个底层数组
			2.切片本身不存储任何数据,都是这个底层数组存储,所以修改切片也就是修改这个数组中的数据
			3.当向切片中添加数据时,如果没有超过容量,直接添加,如果超过容量,自动扩容(成倍增长)
			4.切片一旦扩容,就是重新指向一个新的底层数组

		s1:3--->6--->12--->24

		s2:4--->8--->16--->32....

	*/
	s1 := []int{1, 2, 3}
	fmt.Println(s1)
	fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:3,cap:3
	fmt.Printf("%p\n", s1)

	s1 = append(s1, 4, 5)
	fmt.Println(s1)
	fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:5,cap:6
	fmt.Printf("%p\n", s1)

	s1 = append(s1, 6, 7, 8)
	fmt.Println(s1)
	fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:8,cap:12
	fmt.Printf("%p\n", s1)

	s1 = append(s1, 9, 10)
	fmt.Println(s1)
	fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:10,cap:12
	fmt.Printf("%p\n", s1)

	s1 = append(s1, 11, 12, 13, 14, 15)
	fmt.Println(s1)
	fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:15,cap:24
	fmt.Printf("%p\n", s1)
}


运行结果:

GOROOT=D:\Go #gosetup
GOPATH=C:\Users\DELL\go #gosetup
D:\Go\bin\go.exe build -o C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__1_.exe D:\GolandProjects\Day11-Slice\Slice2.go #gosetup
C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__1_.exe
[1 2 3]
len:3,cap:3
0xc000010180
[1 2 3 4 5]
len:5,cap:6
0xc00000e360
[1 2 3 4 5 6 7 8]
len:8,cap:12
0xc000060120
[1 2 3 4 5 6 7 8 9 10]
len:10,cap:12
0xc000060120
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
len:15,cap:24
0xc00007e000

进程 已完成,退出代码为 0




运行截图:

在这里插入图片描述

代码案例3:

package main

import "fmt"

func main() {
	/*
		slice := arr[start:end]
		 	切片中的数据:[start,end)
		 	arr[:end],从头到end
		 	arr[start:]从start到末尾

		 从已有的数组上,直接创建切片,该切片的底层数组就是当前的数组。
		 	长度是从start到end切割的数据量。
			但是容量从start到数组的末尾。
	*/
	a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	fmt.Println("----------1.已有数组直接创建切片--------------------")
	s1 := a[:5]  //1-5
	s2 := a[3:8] //4-8
	s3 := a[5:]  // 6-10
	s4 := a[:]   // 1-10
	fmt.Println("a:", a)
	fmt.Println("s1:", s1)
	fmt.Println("s2:", s2)
	fmt.Println("s3:", s3)
	fmt.Println("s4:", s4)

	fmt.Printf("%p\n", &a)
	fmt.Printf("%p\n", s1)

	fmt.Println("----------2.长度和容量--------------------")
	fmt.Printf("s1	len:%d,cap:%d\n", len(s1), cap(s1)) //s1	len:5,cap:10
	fmt.Printf("s2	len:%d,cap:%d\n", len(s2), cap(s2)) //s2	len:5,cap:7
	fmt.Printf("s3	len:%d,cap:%d\n", len(s3), cap(s3)) //s3	len:5,cap:5
	fmt.Printf("s4	len:%d,cap:%d\n", len(s4), cap(s4)) //s4	len:10,cap:10

	fmt.Println("----------3.更改数组的内容--------------------")
	a[4] = 100
	fmt.Println(a)
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(s3)

	fmt.Println("----------4.更改切片的内容--------------------")
	s2[2] = 200
	fmt.Println(a)
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(s3)

	fmt.Println("----------4.更改切片的内容--------------------")
	s1 = append(s1, 1, 1, 1, 1)
	fmt.Println(a)
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(s3)
	fmt.Println("----------5.添加元素切片扩容--------------------")
	fmt.Println(len(s1), cap(s1))

	s1 = append(s1, 2, 2, 2, 2, 2)
	fmt.Println(a)
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(s3)
	fmt.Println(len(s1), cap(s1))
	fmt.Printf("%p\n", s1)
	fmt.Printf("%p\n", &a)
}



运行结果:


GOROOT=D:\Go #gosetup
GOPATH=C:\Users\DELL\go #gosetup
D:\Go\bin\go.exe build -o C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__2_.exe D:\GolandProjects\Day11-Slice\Slice3.go #gosetup
C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__2_.exe
----------1.已有数组直接创建切片--------------------
a: [1 2 3 4 5 6 7 8 9 10]
s1: [1 2 3 4 5]
s2: [4 5 6 7 8]
s3: [6 7 8 9 10]
s4: [1 2 3 4 5 6 7 8 9 10]
0xc000018190
0xc000018190
----------2.长度和容量--------------------
s1      len:5,cap:10
s2      len:5,cap:7
s3      len:5,cap:5
s4      len:10,cap:10
----------3.更改数组的内容--------------------
[1 2 3 4 100 6 7 8 9 10]
[1 2 3 4 100]
[4 100 6 7 8]
[6 7 8 9 10]
----------4.更改切片的内容--------------------
[1 2 3 4 100 200 7 8 9 10]
[1 2 3 4 100]
[4 100 200 7 8]
[200 7 8 9 10]
----------4.更改切片的内容--------------------
[1 2 3 4 100 1 1 1 1 10]
[1 2 3 4 100 1 1 1 1]
[4 100 1 1 1]
[1 1 1 1 10]
----------5.添加元素切片扩容--------------------
9 10
[1 2 3 4 100 1 1 1 1 10]
[1 2 3 4 100 1 1 1 1 2 2 2 2 2]
[4 100 1 1 1]
[1 1 1 1 10]
14 20
0xc0000240a0
0xc000018190

进程 已完成,退出代码为 0



运行截图:

在这里插入图片描述

代码案例4:

package main

import "fmt"

func main() {
	/*

		按照类型来分:
			基本类型:int,float,string,bool
			复合类型:array,slice,map,struct,pointer,function,chan

		按照特点来分:
			值类型:int,float,string,bool,array
				传递的是数据副本
			引用类型:Slice
				传递的地址,多个变量指向了同一块内存地址,



		所以:切片是引用类型的数据,存储了底层数组的引用
	*/

	//1.数组:值类型
	a1 := [4]int{1, 2, 3, 4}
	a2 := a1 //值传递:传递的是数据
	fmt.Println(a1, a1)
	a1[0] = 100
	fmt.Println(a1, a2)

	//2.切片:引用类型
	s1 := []int{1, 2, 3, 4}
	s2 := s1
	fmt.Println(s1, s2)
	s1[0] = 100
	fmt.Println(s1, s2)

	fmt.Printf("%p\n", s1)
	fmt.Printf("%p\n", s2)
	fmt.Printf("%p\n", &s1)
	fmt.Printf("%p\n", &s2)

	//1. `fmt.Printf("%p\n", s1)`:这行代码中的`%p`是格式化字符串,用于打印指针的值。`s1`是一个变量,通过使用`%p`格式化字符串,我们可以打印出`s1`变量的内存地址。

	//2. `fmt.Printf("%p\n", s2)`:同样地,这行代码用于打印`s2`变量的内存地址。通过使用`%p`格式化字符串,我们可以获取`s2`变量的内存地址。

	//	3. `fmt.Printf("%p\n", &s1)`:这行代码中的`&`符号用于获取`s1`变量的地址。然后,通过使用`%p`格式化字符串,我们可以将`s1`变量的地址打印出来。

	//4. `fmt.Printf("%p\n", &s2)`:同样地,这行代码用于打印`s2`变量的地址。通过使用`%p`格式化字符串,我们可以获取`s2`变量的地址。

}



运行结果:


GOROOT=D:\Go #gosetup
GOPATH=C:\Users\DELL\go #gosetup
D:\Go\bin\go.exe build -o C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__3_.exe D:\GolandProjects\Day11-Slice\Slice4.go #gosetup
C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__3_.exe
[1 2 3 4] [1 2 3 4]
[100 2 3 4] [1 2 3 4]
[1 2 3 4] [1 2 3 4]
[100 2 3 4] [100 2 3 4]
0xc000012200
0xc000012200
0xc000008078
0xc000008090

进程 已完成,退出代码为 0



运行截图:

在这里插入图片描述

代码案例5:


package main

import "fmt"

func main() {
	/*
		深拷贝:拷贝的是数据本身。
			值类型的数据,默认都是深拷贝:array,int,float,string,bool,struct


		浅拷贝:拷贝的是数据 地址。
			导致多个变量指向同一块内存
			引用类型的数据,默认都是浅拷贝:slice,map,

			因为切片是引用类型的数据,直接拷贝的是地址。

		func copy(dst, src []Type) int
			可以实现切片的拷贝

	*/

	s1 := []int{1, 2, 3, 4}
	s2 := make([]int, 0) //len:0,cap:0
	for i := 0; i < len(s1); i++ {
		s2 = append(s2, s1[i])
	}
	fmt.Println(s1)
	fmt.Println(s2)

	s1[0] = 100
	fmt.Println(s1)
	fmt.Println(s2)

	//copy()
	s3 := []int{7, 8, 9}
	fmt.Println(s2)
	fmt.Println(s3)

	//copy(s2,s3) //将s3中的元素,拷贝到s2中
	//copy(s3,s2) //将s2中的元素,拷贝到s3中
	copy(s3[1:], s2[2:])

	//[1:] 和 [2:] 表示切片的切片操作,用于指定切片的起始位置。在这个例子中,[1:] 表示将目标切片的起始位置从索引1开始(即去掉了第一个元素),[2:] 表示将源切片的起始位置从索引2开始(即去掉了前两个元素)。
	fmt.Println(s2)
	fmt.Println(s3)

	//copy(s3[1:], s2[2:]) 的作用是将源切片 s2 中从索引2开始(包括索引2)的元素复制到目标切片 s3 中,从索引1开始(包括索引1)的位置开始填充。

}


运行结果:

GOROOT=D:\Go #gosetup
GOPATH=C:\Users\DELL\go #gosetup
D:\Go\bin\go.exe build -o C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__4_.exe D:\GolandProjects\Day11-Slice\Slice5.go #gosetup
C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day11_Slice__4_.exe
[1 2 3 4]
[1 2 3 4]
[100 2 3 4]
[1 2 3 4]
[1 2 3 4]
[7 8 9]
[1 2 3 4]
[7 3 4]

进程 已完成,退出代码为 0




运行截图:

在这里插入图片描述

今日学习总结:

今天我学习了Golang中的切片(Slice),通过本文的学习,我深入了解了切片的概念、语法以及常用函数的使用。我学会了如何修改切片、获取切片的长度和容量,并掌握了append()和copy()函数的功能和应用场景。切片是Golang中非常重要的数据结构,对于提高代码的灵活性和效率有着重要的作用。希望本文能够帮助读者加深对切片的理解和应用。

通过学习本篇文章,希望读者了解了切片的概念、语法以及基本操作的使用方式。掌握了len()、cap()、append()和copy()等常用函数的功能和使用方法。切片在Golang中的应用非常广泛,对于大数据集合的处理以及动态扩容等场景非常实用。切片的灵活性和效率使得它成为Golang中重要的数据结构之一。如果你对Golang的切片还有更多的疑问,可以继续学习Golang的高级切片特性或查阅相关的官方文档。祝你在Golang的切片世界中玩得开心!

在这里插入图片描述

结语

通过今天的学习,您已经踏上了Golang的学习之旅。在未来的日子里,您将探索Golang的各个方面,从基础概念到高级技巧,从实际应用到性能优化。
学习一门编程语言是一个持续的过程,每一天都是您向Golang的精通迈进的重要一步。我鼓励您坚持每天学习,保持热情和好奇心,解决挑战并享受成功的喜悦。

在您的学习旅程中,不要忘记参与社区和与其他Golang开发者交流。分享您的见解和经验,向他人学习,并在开源项目或实际应用中展示您的技能。

如果您在学习过程中遇到困难或有任何问题,不要犹豫向社区和专家寻求帮助。持续学习,勇敢探索,您将在Golang领域取得令人瞩目的成就。

最后,感谢您的阅读和支持!祝愿您在未来的每一天中都能够成为一名精通Golang的开发者!

期待听到您在学习过程中的进展和成就。如果您需要进一步的帮助,请随时告诉我。祝您在学习Golang的旅程中取得巨大成功!

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

如果您在学习过程中有任何疑惑,请点击下方名片,带您一对一快速入门 Go语言 的世界 ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/697588.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

期望最大化注意力网络 EMANet

论文&#xff1a;Expectation-Maximization Attention Networks for Semantic Segmentation Github&#xff1a;https://github.com/XiaLiPKU/EMANet ICCV2019 oral 论文提出的期望最大化注意力机制Expectation- Maximization Attention (EMA)&#xff0c;摒弃了在全图上计算注…

再述时序约束

再述时序约束 一、为什么要加时序约束&#xff1f;二、时序分析是什么&#xff1f;三、时序分析的一些基本概念三、 时序分析的一些基本公式 一、为什么要加时序约束&#xff1f; 一次笔者在调试HDMI输出彩条&#xff0c;出现彩条时有时无现象&#xff0c;笔者视频输出芯片的驱…

leecode-数组多数-摩尔投票法

题目 题目 分析 最开始思路&#xff1a;排序&#xff0c;然后取nums[n/2]&#xff0c;但是时间复杂度不过关。 摩尔投票法&#xff0c;学到了&#xff01; 代码 class Solution { public:int majorityElement(vector<int>& nums) {//摩尔投票int cnt0;int targ…

计算机二级c语言题库

计算机C语言二级考试&#xff08;60道程序设计&#xff09; 第1道 请编写一个函数fun,它的功能是:将ss所指字符串中所有下标为奇数位置上的字母转换成大写&#xff08;若该位置上不是字母&#xff0c;则不转换&#xff09;。 例如&#xff0c;若输入"abc4EFG"&…

OpenCV学习笔记 | ROI区域选择提取 | Python

摘要 ROI区域是指图像中我们感兴趣的特定区域&#xff0c;OpenCV提供了一些函数来选择和提取ROI区域&#xff0c;我们可以使用OpenCV的鼠标事件绑定函数&#xff0c;然后通过鼠标操作在图像上绘制一个矩形框&#xff0c;该矩形框即为ROI区域。本文将介绍代码的实现以及四个主要…

opencv编译

文章目录 一、编译前工作二、编译安装1、Windows2、Linux 一、编译前工作 进入下载页面https://github.com/opencv/opencv&#xff0c;下载指定.tar.gz源码包&#xff0c;例如&#xff1a;opencv-4.7.0.tar.gz。解压到指定目录。 二、编译安装 opencv构建时&#xff0c;需要…

使用docker搭建hadoop集群

1.下载安装docker 2.启动docker 3.配置docker镜像 4.获取hadoop镜像 5.拉取hadoop镜像 6.运行容器 7.进入容器 8.配置免密 9.格式化节点 10.启动节点 11.查看节点信息 (img-CBr9VbGk-1687962511910)] 11.查看节点信息

javascript原型、原型链、继承详解

一、原型和原型链的基本概念 在JavaScript中&#xff0c;每个对象都有一个原型对象&#xff08;prototype&#xff09;。原型对象就是一个普通的对象&#xff0c;在创建新对象时&#xff0c;可以将该对象作为新对象的原型。原型对象可以包含共享的属性和方法&#xff0c;这些属…

Appium自动化-ADB连接手机提示unauthorized

目录 开头&#xff1a; 问题&#xff1a; 调研&#xff1a; 重启大法 终极大法 总结&#xff1a; 开头&#xff1a; 当使用ADB&#xff08;Android Debug Bridge&#xff09;连接手机时&#xff0c;如果提示"unauthorized"&#xff08;未授权&#xff09;错误&a…

javaee HttpSessionListener监听器统计在线人数

先创建ServletContextListener 在全局对象application中设置count属性 package com.yyy.listener;import java.util.ArrayList;import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax…

易基因|表观遗传学与脑卒中:DNA甲基化的作用及衰老对血脑屏障修复的影响

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 脑卒中&#xff08;俗称中风&#xff09;是导致死亡和长期残疾的主要原因&#xff0c;尤其是对于老龄人来说。脑卒中的平均生存时间为6-7年&#xff0c;许多患者存在身体残疾和晚期认知功…

技术岗/算法岗面试如何准备?5000字长文、6个角度以2023秋招经历分享面试经验

技术岗/算法岗面试流程是什么样的&#xff1f;技术面都干什么&#xff1f;Coding 机试如何准备&#xff1f;技术面考察哪些知识&#xff0c;如何准备&#xff1f;项目八股如何准备&#xff1f;简历要注意什么&#xff1f;怎么做&#xff1f; 大家好&#xff0c;我是卷了又没卷…

uniapp 适配全面屏

1、manifest.json 文件修改 app-plus 下 添加 "safearea": {"background": "#00000000","bottom": {"offset": "auto"}},2、部分页面设置全屏&#xff08;登录页面&#xff09; methods: {//设置页面全屏onShow(…

SpringBoot(二)starter介绍

做Java后端的同学可能都知道&#xff0c;在SpringBoot诞生之前&#xff0c;还有传统的Spring。这种Spring项目想要运行&#xff0c;需要导入各种依赖&#xff0c;而且还要在 XML 配置文件中一顿配置&#xff0c;非常痛苦。但通过上篇博客我们可以看到&#xff0c;SpringBoot项目…

事务与隔离级别

事务四要素 原子性&#xff08;Atomicity&#xff09;&#xff1a;要么全部完成&#xff0c;要么全部不完成&#xff1b;一致性&#xff08;Consistency&#xff09;&#xff1a;一个事务单元需要提交之后才会被其他事务可见&#xff1b;隔离性&#xff08;Isolation&#xff…

azure databricks因为notebook 日志打多或者打印图片太多,往下拉卡死怎么处理

1、同事碰到个问题&#xff0c;databricks 页面卡死不动了 2、我。。。。。。。。测试了下搞不定&#xff0c;找azure的工程师&#xff0c;特此笔记如下图 !](https://img-blog.csdnimg.cn/5db9756d0e224d15a9a607561b47591f.png)

怎样自定义starter模块和使用

一、 自定义Starter模块 在实际开发中&#xff0c;经常会定义一些公共组件&#xff0c;提供给各个项目团队使用。而在SpringBoot的项目中&#xff0c;一般会将这些公共组件封装为SpringBoot的starter(起步依赖)。 1.1实例–阿里云OSS的配置 前言&#xff1a;我们在使用阿里云…

windows下MySQL 5.7.31的安装

文章目录 安装步骤检查是否安装成功配置环境变量 安装步骤 双击安装包mysql-installer-community-5.7.31.0.msi选择自定义安装“custom”&#xff0c;点击next “Developer Default”是开发者默认“Server only”仅作为服务器安装“Clientonly”仅作为客户端安装“Full”是完…

华为OD机试真题 Python 实现【红黑图】【2023Q1 200分】,附详细解题思路

一、题目描述 众所周知红黑树是一种平衡树&#xff0c;它最突出的特性就是不能有两个相邻的红色节点。 那我们定义一个红黑图&#xff0c;也就是一张无向图中&#xff0c;每个节点可能有红黑两种颜色&#xff0c;但我们必须保证没有两个相邻的红色节点。 现在给出一张未染色的…

晶振的作用,高速晶振优缺点

前言 &#xff08;1&#xff09;我们都知道晶振是一款MCU的心脏&#xff0c;因为长期用这种抽象的概念进行解释&#xff0c;导致很多人不知道这个心脏的实际作用。因此&#xff0c;我在这里详细的介绍一下晶振对于MCU的实际作用。 &#xff08;2&#xff09;接下来我将会在MCU处…