Go语言:数组和切片

  Python中的数组(这里指的是List类型)及其切片Slice基本相同,但在Go语言中这两者差别很大。

1 数组

Go语言中的数组(Array)存放的是长度固定(不能增长或收缩)、类型固定并且存储位置连续的一系列元素。

1.1 创建

Go语言中数组的创建方式如下:

	arr1 := [5]string{
    
    "a", "b", "c", "d", "e"}
	arr2 := [...]string{
    
    "g", "h", "i"} //自动推导出数组长度,省略号不可忽略。如果省略了...,arr2的类型就变成了切片
	arr3 := [5]string{
    
    1: "j", 2: "k"}  //指定索引为1和2的元素值,其余默认为空
	arr4 := [100]int{
    
    } //创建一个保存1到100的整数的数组
	for i := 0; i < len(arr4); i++ {
    
    
		arr4[i] = i + 1
	}
	//二维数组初始化
	arr5 :=[5][2]int{
    
    {
    
    1,2},{
    
    2,3}}
	fmt.Println(arr5)

关于数组的声明需要注意几点:

  • 当创建一个数组时,没有使用字面量初始化的数组元素会被初始化为该数组保存类型的零值。
  • 数组的长度必须是常量,不可以是变量(这点和C语言一样),以下的写法是错误的。
a:=[5]int{1,2,3,4,5}
b:=[len(a)]int //编译不通过
1.2 遍历

Go语言中数组的遍历可以使用range。具体如下:

package main

import (
	"fmt"
	"strconv"
)

func main() {
    
    
	arr0 := [3]string{
    
    "hello", "nihao", "dajiahao"}
	for i, v := range arr0 {
    
    
		fmt.Println("数组arr0的第" + strconv.Itoa(i) + "个元素为:" + v)
	}
	arr1 := [100]int{
    
    } //创建一个保存1到100的整数的数组
	for i := 0; i < len(arr1); i++ {
    
    
		arr1[i] = i + 1
	}
	sum1 := 0 //计算1+2+3+……+100
	//range arr1返回两个数据,第一个为元素索引,对于后续计算无用,用_接收
	for _, v := range arr1 {
    
    
		sum1 += v
	}
	fmt.Println("1到100的相加总和为:" + strconv.Itoa(sum1))
}

2 切片

Go语言的切片底层就是用数组来实现的,所以切片也是由多个相同类型的元素组成的。可以把切片看成是对应数组的视图。

2.1 创建

Go语言中常用的切片的创建方法如下:

package main
import (
	"fmt"
	"strconv"
)
func main() {
    
    
	array := [7]int{
    
    1, 2, 3, 4, 5, 6, 7}
	slice0 := array[2:6] //利用数组生成切片
	fmt.Println("slice0更改前:", slice0)
	slice0[1] = 10
	fmt.Println("slice0更改后:", slice0)
	fmt.Println("slice0更改后的array:", array)
	slice1 := []string{
    
    "a", "b", "c"} //中括号里面不要加...
	fmt.Println("切片slice1:", slice1)
	slice2 := make([]string, 4, 8) //声明一个长度为4,容量为8的空切片
	fmt.Println("切片slice2:", slice2)
	fmt.Println("切片slice2,长度为:" + strconv.Itoa(len(slice2)) + ",容量为:" + strconv.Itoa(cap(slice2)))
	slice3 := make([]int, 4, 8)
	fmt.Println("切片slice3:",slice3)}

其执行结果如下:

slice0更改前: [3 4 5 6]
slice0更改后: [3 10 5 6]
slice0更改后的array: [1 2 3 10 5 6 7]
切片slice1: [a b c]
切片slice2: [ ]
切片slice2,长度为:4,容量为:8
切片slice3: [0 0 0 0]

关于切片有以下几点说明:

  • 利用数组生成的切片,切片和原数组指向的是同一片内存空间,所以对切片中的数据进行修改,底层数组的值也会跟着修改。
  • 切片的长度和容量不是一回事。Go语言给slice2分配了一块容量为8的内存空间,但目前只有4个内存空间有元素(“”)。
  • 切片的循环遍历方法与数组相同,这里不再详细介绍。
  • make()函数声明切片时,如果指定了长度,那么响应位置的变量为赋值为类型初值。
2.2 append函数

Go语言中的切片可以看作是不定长数组,可以通过append函数向切片中添加元素,并返回新切片

package main
import "fmt"
func main() {
    
    
	slice2 := []string{
    
    "2", "3", "3"}
	slice3 := make([]string, 4, 8)
	fmt.Println("slice3的内存地址:", &slice3[0])
	slice4 := []string{
    
    "f", "g"}
	slice3 = append(slice3, slice4...)
	fmt.Println("slice3的内存地址:", &slice3[0])
	slice3 = append(slice3, slice2...)
	fmt.Println("slice3的内存地址:", &slice3[0])
	fmt.Println(slice3)
}

其执行结果如下:

slice3的内存地址: 0xc00011c000
slice3的内存地址: 0xc00011c000
slice3的内存地址: 0xc000122000
[ f g 2 3 3]

这里要注意以下几点:

  • append()中的参数可以是单个字符,也可以是切片类型,但不可以是数组。
  • 当切片的容量未满时,往切片内添加新的元素时,新元素会追加在原切片元素的后面。若切片容量满了,则会开辟一片新的内存空间。
  • 如果多个切片共享同一个底层数组,只要有一个切片做了修改,所以的切片变量都会跟着变动。
  • 调用append函数,通常是将函数的返回值赋给你传入的那个切片变量,这样就不会导致两个切片共享同一个底层数组了。

补充1:省略号…

  • 在函数声明中的最后的或者仅有的参数类型前添加省略号,表示该函数的参数是可变长的。同时,当需要将切片形式的多个元素传递给可变长参数时,需要在切片变量的后面加省略号。举例如下:
package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
)

func computer_average(numArray ...int) float64 {
    
    
	sum := 0
	for _, item := range numArray {
    
    
		sum += item
	}
	return float64(sum) / float64(len(numArray))
}

func readIntArray(input string) []int {
    
    
	input = strings.Trim(input, "\n")
	inputList := strings.Split(input, " ")
	numArray := make([]int, 0, len(inputList))
	for _, item := range inputList {
    
    
		item, err := strconv.Atoi(item)
		if err == nil {
    
    
			numArray = append(numArray, item)
		}
	}
	return numArray
}
func main() {
    
    
	fmt.Println("输入一个Int型整数:")
	reader := bufio.NewReader(os.Stdin)
	input, err := reader.ReadString('\n')
	if err != nil {
    
    
		log.Fatal(err)
	}
	numArray := readIntArray(input)
	//computer_average只接收一个参数
	fmt.Printf("平均值为:%.2f\n", computer_average(numArray[0]))
	fmt.Println("输入多个Int型整数:")
	reader = bufio.NewReader(os.Stdin)
	input, err = reader.ReadString('\n')
	if err != nil {
    
    
		log.Fatal(err)
	}
	numArray = readIntArray(input)
	//computer_average接收多个参数
	fmt.Printf("平均值为:%.2f\n", computer_average(numArray...))
}

其代码执行结果如下:

当numList只接收一个参数时:
输入一个Int型整数:
12
[12]
readintarray [12]
12
平均值为:12.00
当numList只接收一个参数时:
输入多个Int型整数:
12 34
[12 34]
readintarray [12 34]
46
平均值为:23.00

补充2:接收多种类型的数组/切片

正如前文所述,go语言中的切片和数组中元素类型是固定的,但当这个类型为接口interface时,就可以组成一个由多种类型元素组成的切片或数组。举例如下:

func main() {
    
    
	a := []interface{
    
    }{
    
    1, "hello", 4.5}
	fmt.Println(a)
}

猜你喜欢

转载自blog.csdn.net/yeshang_lady/article/details/134040586