切片的底层是数组 append 当原有容量不够时将会创建一个新的数组,并将原有的值复制到新数组里面。容量小于1000时会以两倍的形式增长,超过1000后以1.25倍的形式增长。

append可以合并多个切片,append(s1, s2 ...)

// 创建两个切片,并分别用两个整数进行初始化
s1 := []int{1, 2}
s2 := []int{3, 4}
// 将两个切片追加在一起,并显示结果
fmt.Printf("%v\n", append(s1, s2...))
Output:
[1 2 3 4]

限制切片长度可以在调用append 时创建一个新的底层数组,防止修改切片时影响到底层数组。

source := []string{"Apple", "Orange", "Plum", "Banana", "Grape"} 
slice := source[2:3:3] // 限制容量
slice = append(slice, "Kiwi") // 这样就不会修改掉 Banana,而是在一个新的底层数组中操作了

迭代切片:range 创建了每个元素的副本,而不是直接返回对该元素的引用

// 创建一个整型切片
// 其长度和容量都是 4 个元素
slice := []int{10, 20, 30, 40}
// 迭代每一个元素,并显示其值
for index, value := range slice {
fmt.Printf("Index: %d Value: %d\n", index, value)
}
Output:
Index: 0 Value: 10
Index: 1 Value: 20
Index: 2 Value: 30
Index: 3 Value: 40

查看切片长度容量:

package main

import "fmt"

func main() {
	a := []int{1, 2, 3, 4, 5}
	s := a[1:3:5]                    //[开始位置 : 结束位置 : 切片容量]
	fmt.Println("s = ", s)           //s =  [2 3]
	fmt.Println("len(s) = ", len(s)) //长度 len(s) =  2 也就是 3-1
	fmt.Println("cap(s) = ", cap(s)) //容量 cap(s) =  4 也就是 5-1
}

切片和数组的区别:

package main

import "fmt"

func main() {
	a := [5]int{} // 数组[]里面是固定值
	s := []int{}  // 切片[]里面为空或...
	fmt.Println(a)

	s = append(s, 123)
	fmt.Println(cap(s), len(s), s)
}

切片创建函数 make:

package main

import "fmt"

func main() {
	s2 := make([]int, 5, 10)          // make(切片类型,长度,容量)
	fmt.Println(s2, len(s2), cap(s2)) //[0 0 0 0 0] 5 10

	s3 := make([]int, 5)              //默认容量和长度一样
	fmt.Println(s3, len(s3), cap(s3)) //[0 0 0 0 0] 5 5
}

截取切片:

package main

import "fmt"

func main() {
	array := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	s1 := array[:] // 截取全部 [1 2 3 4 5 6 7 8 9]
	fmt.Println(s1)

	s2 := array[2] // 引用元素 3
	fmt.Println(s2)

	s3 := array[1:2:3] // 截取部分 [2]
	fmt.Println(s3)

	s4 := array[:6] // 从零开始截取6个 [1 2 3 4 5 6]
	fmt.Println(s4)

	s5 := array[3:] // 从第三个开始截取到最后 [4 5 6 7 8 9]
	fmt.Println(s5)

	s6 := array[2:5] // 从array[2]开始截取5-2个元素 [3 4 5]
	fmt.Println(s6)

	s6[1] = 666        // 改变新切片的值,原切片的值也会被改变
	fmt.Println(s6)    // [3 666 5]
	fmt.Println(array) // [1 2 3 666 5 6 7 8 9]
}

追加元素 append:

package main

import "fmt"

func main() {
	s1 := []int{}
	fmt.Println(s1) // []

	s1 = append(s1, 1)
	fmt.Println(s1, cap(s1)) // [1] 1
	s1 = append(s1, 2)
	fmt.Println(s1, cap(s1)) // [1 2] 2
	s1 = append(s1, 3)
	fmt.Println(s1, cap(s1)) // [1 2 3] 4  如果超过原来的容量则以两倍的方式进行扩容
}

切片的拷贝 copy:

package main

import "fmt"

func main() {
	src := []int{8, 9}
	dst := []int{1, 2, 3, 4, 5, 6}

	copy(dst, src)
	fmt.Println(dst) // [8 9 3 4 5 6] 覆盖原来的元素
}

切片做函数参数:

        切片作为函数参数只是复制切片,并没有复制切片指向的底层数组。64 位架构的机器上,一个切片需要 24 字节的内存:指针字段需要 8 字节,长度和容量字段分别需要 8 字节。切片作为函数参数只是复制了24字节。

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func InitData(s []int) {
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < len(s); i++ {
		s[i] = rand.Intn(100)
	}
}

func main() {
	n := 10
	s := make([]int, n)
	InitData(s)
	fmt.Println(s)
}

小练习:猜四位数

package main

import (
	"fmt"
	"math/rand"
	"time"
)

/**
* 创建随机数
* @param p *int 用来存放随机数的指针
 */
func CreateNum(p *int) {
	rand.Seed(time.Now().UnixNano())
	var num int
	for {
		num = rand.Intn(10000)
		if num > 1000 {
			break
		}
	}
	*p = num
}

/**
* 将创建的随机数放入切片以备后面使用
* @param s []int 用来存放随机数的切片
* @param num int 一个4位随机数
 */
func PutSlice(s []int, num int) {
	s[0] = num / 1000
	s[1] = num % 1000 / 100
	s[2] = num % 100 / 10
	s[3] = num % 10
}

/**
* 获取用户输入的4位数
* @param s []int 存放4位数的切片
 */
func GetInputNumber(s []int) {
	var num int
	for {
		fmt.Println("请输入一个4位数:")
		fmt.Scan(&num)
		if num < 10000 && num > 999 {
			break
		}
		fmt.Println("输入错误!")
	}
	PutSlice(s, num)
}

func main() {
	var randNum int
	CreateNum(&randNum)
	randNumber := make([]int, 4)

	// 产生一个随机数放入切片
	PutSlice(randNumber, randNum)
	inputNumber := make([]int, 4)

	for {
		// 获取随机数放入切片
		GetInputNumber(inputNumber)

		// 比较四位数
		n := 0
		for i := 0; i < 4; i++ {
			if randNumber[i] > inputNumber[i] {
				fmt.Printf("第 %d 位小了\n", i+1)
			} else if randNumber[i] < inputNumber[i] {
				fmt.Printf("第 %d 位大了\n", i+1)
			} else {
				fmt.Printf("第 %d 位猜对了\n", i+1)
				n++
			}
		}

		if n == 4 {
			fmt.Println("全猜对了")
			break
		}
	}
}