该文章Github地址:https://github.com/AntonyCheng/go-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】
在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】& CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!
上一章:由浅到深认识Go语言(8):切片
9.切片
数组的思考
数组定义完之后,长度是固定的,一旦遇到动态变化的程序,数组使用就可能非常麻烦,所以Go语言提出了切片的概念,可以把切片理解成“动态数组”,但是他本质不是数组,在以后的编程中,切片会逐渐替代掉数组;
9.1.切片创建
//切片创建有三种方式:
//1.var 切片名 []数据类型
//2.切片名 := []数据类型
//3.使用make()函数创建:
// 3.1.make(切片类型,长度,容量)
// 切片类型就是 []数据类型
// 长度就是 初始化后真实存在的元素个数
// 容量就是 初始化最大能包含的元素个数
// 注意:容量 >= 长度
// 3.2.make(切片类型,容量)
// 这种参数列表的容量和长度相同;
package main
import "fmt"
func main() {
var num1 []int
fmt.Println("num1 =", num1, ",len(num1) =", len(num1), ",cap(num1) =", cap(num1))
num2 := []int{}
fmt.Println("num2 =", num2, ",len(num2) =", len(num2), ",cap(num2) =", cap(num2))
num3 := make([]int, 0, 0)
fmt.Println("num3 =", num3, ",len(num3) =", len(num3), ",cap(num3) =", cap(num3))
num4 := make([]int, 3)
fmt.Println("num4 =", num4, ",len(num4) =", len(num4), ",cap(num4) =", cap(num4))
}
打印效果如下:
9.2.切片初始化
package main
import "fmt"
func main() {
var num1 []int
fmt.Println("num1 =", num1, ",len(num1) =", len(num1), ",cap(num1) =", cap(num1))
num1 = append(num1, 1, 2, 3, 4, 5)
fmt.Println("num1 =", num1, ",len(num1) =", len(num1), ",cap(num1) =", cap(num1))
num1 = append(num1, 6, 7, 8, 9, 10)
fmt.Println("num1 =", num1, ",len(num1) =", len(num1), ",cap(num1) =", cap(num1))
num2 := []int{1, 2, 3, 4, 5}
fmt.Println("num2 =", num2, ",len(num2) =", len(num2), ",cap(num2) =", cap(num2))
num2 = append(num2, 6, 7, 8, 9, 10)
fmt.Println("num2 =", num2, ",len(num2) =", len(num2), ",cap(num2) =", cap(num2))
num3 := make([]int, 10)
fmt.Println("num3 =", num3, ",len(num3) =", len(num3), ",cap(num3) =", cap(num3))
//这里循环条件是小于长度,而不是容量
for i := 0; i < len(num3); i++ {
num3[i] = i + 1
}
fmt.Println("num3 =", num3, ",len(num3) =", len(num3), ",cap(num3) =", cap(num3))
}
打印效果如下:
9.3.切片的遍历
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for i := 0; i < len(nums); i++ {
fmt.Printf("%d ", nums[i])
}
fmt.Println()
for _, v := range nums {
fmt.Printf("%d ", v)
}
}
打印效果如下:
9.4.切片的截取
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println("len(nums) =", len(nums), ",cap(nums) =", cap(nums))
fmt.Println("nums[1] =", nums[1])
fmt.Println("nums[:] =", nums[:])
fmt.Println("nums[5:] =", nums[5:])
fmt.Println("nums[:5] =", nums[:5])
fmt.Println("nums[3:7] =", nums[3:7])
//nums[low:high:max]中 max >= high >= low
fmt.Println("nums[3:7:5] =", nums[3:7:7])
}
打印效果如下:
问题:如果我们将切片截取后返回新切片。对新切片的值进行修改,会影响原切片么;
package main
import "fmt"
func main() {
num1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
num2 := []int{}
num2 = num1[1:5]
fmt.Println(num1)
fmt.Println(num2)
num2[0] = 999
fmt.Println(num1)
fmt.Println(num2)
}
打印效果如下:
关于切片截取的问题,在Go语言中会影响原来的切片,和Java中ArrayList相似;
9.5.append函数扩容机制
一般扩容方式是扩容至扩容前容量的2倍,如果超过1024字节,每次扩容至扩容前的1.25倍;Java中扩容机制是扩容至扩容前的1.5倍;
package main
import "fmt"
func main() {
num := make([]int, 3, 5)
num = append(num, 1)
num = append(num, 2)
fmt.Println("len(num) =", len(num))
fmt.Println("cap(num) =", cap(num))
num = append(num, 3)
fmt.Println("len(num) =", len(num))
fmt.Println("cap(num) =", cap(num))
}
打印效果如下:
9.6.copy拷贝函数
基本结构
//将切片2拷贝至切片1
copy(切片1,切片2)
示例如下:
package main
import "fmt"
func main() {
num1 := []int{1, 2, 3, 4}
num2 := []int{5, 6, 7, 8}
fmt.Println("num1 =", num1)
fmt.Println("num2 =", num2)
copy(num1, num2)
fmt.Println("num1 =", num1)
fmt.Println("num2 =", num2)
}
打印效果如下:
如果拷贝的两个切片长度不一致,那么拷贝的长度为两个切片中长度较小的长度值;
package main
import "fmt"
func main() {
num1 := []int{1, 2}
num2 := []int{5, 6, 7, 8}
fmt.Println("num1 =", num1)
fmt.Println("num2 =", num2)
copy(num1, num2)
fmt.Println("num1 =", num1)
fmt.Println("num2 =", num2)
}
打印效果如下:
9.7.切片作为函数参数
package main
import "fmt"
func main() {
num := []int{1, 2, 3, 4}
ints := add1(num)
fmt.Println(ints)
}
func add1(num []int) []int {
fmt.Println("原切片如下:")
for _, v := range num {
fmt.Printf("%d ", v)
}
fmt.Println()
num = append(num, 1)
fmt.Println("已经添加数字1")
return num
}
打印效果如下:
如果传入后对其中的值进行了修改,原来的切片也会被一并修改,这个和数组就有区别了,和Java中的ArrayList类似;
package main
import "fmt"
func main() {
num := []int{1, 2, 3, 4, 5}
updateAllZero(num)
fmt.Println("修改后的切片:")
fmt.Println(num)
}
func updateAllZero(num []int) {
fmt.Println("原切片如下:")
for _, v := range num {
fmt.Printf("%d ", v)
}
fmt.Println()
for i := 0; i < len(num); i++ {
num[i] = 0
}
}
打印效果如下:
append() 函数本就返回了一个切片,并不是对原切片进行的操作,所以没办法改变原切片;
9.8.切片案例
案例一:
计算出一组整型数据之和;(Go与C语言类似,不能在创建数组时使用变量作为数组个数)
package main
import (
"fmt"
)
func main() {
num := 0
sum := 0
fmt.Println("请输入你要输入的数的个数:")
fmt.Scan(&num)
arr := make([]int, num)
for i := 0; i < len(arr); i++ {
fmt.Println("请输入第", i+1, "个数:")
fmt.Scan(&arr[i])
sum += arr[i]
}
fmt.Printf("sum = %d\n", sum)
}
打印效果如下:
案例二:
输出一组整型数据最大的值;
package main
import (
"fmt"
)
func main() {
num := 0
fmt.Println("请输入你要比较的数的个数:")
fmt.Scan(&num)
arr := make([]int, num)
for i := 0; i < len(arr); i++ {
fmt.Println("请输入第", i+1, "个数:")
fmt.Scan(&arr[i])
}
max := arr[0]
for i := 0; i < len(arr); i++ {
if arr[i] > max {
max = arr[i]
}
}
fmt.Println("max =", max)
}
打印效果如下:
9.9.排序
9.9.1.冒泡排序
package main
import "fmt"
func main() {
num := []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}
for i := 0; i < len(num); i++ {
for j := 0; j < i; j++ {
if num[j] >= num[i] {
temp := num[j]
num[j] = num[i]
num[i] = temp
}
}
fmt.Println(num)
}
}
打印效果如下:
9.9.2.选择排序
package main
import "fmt"
func main() {
num := []int{38, 20, 46, 38, 74, 91, 12, 25}
for i := 0; i < len(num); i++ {
min := num[i]
index := i
for j := i; j < len(num); j++ {
if num[j] < min {
min = num[j]
index = j
}
}
temp := num[i]
num[i] = min
num[index] = temp
fmt.Println(num)
}
}
打印效果如下: