欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

go 语言教程(一):切片和数组

程序员文章站 2024-01-29 23:45:52
...

一:go语言数组

         在go语言当中,数组定义有很多种方式,常用的如下所示:

package main

import "fmt"
//go 数组

func updateArray(s [5]int){
	s[0] = 200
}

func main() {
	var arr1 int//等价于 var arr1 [0]int
	arr2 := [3]int{1,3,4}
	arr3 := [...]int{1,3,45,677,889}//编译器自动推断数组大小
	var grid [4][5]int//4行5列数组 [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
	fmt.Println(arr1, arr2, arr3)
	fmt.Println(grid)
	for i,v := range arr3 {
		fmt.Println(i, v)
	}

	fmt.Println("After update array")
	updateArray(arr3)
	//updateArray(arr1)//编译错误
	fmt.Println(arr3)//[1 3 45 677 889]
}

        在go语言当中,type [2]int 和type [5]int将会被看作是不同类型,所以上面updateArray(arr1)会报编译错误。同时,go语言当中对数组的传递是值传递,传递过程中是对原数组的拷贝,在updateArray方法中对数组的元素进行改变,是不会改变原数组的值得。因此,更多的用到的是切片(Slice)

二:go语言切片

        切片的含义是数组的一个view(视图),对切片当中的元素进行更改的时候,能够直接映射到原数组。切片的使用如下:

package main

import "fmt"

//go语言当中array传递不能改变其值,而是拷贝,一般我们用切片

func updateSlice(s []int) {
	s[0] = 100
}

func main(){
	arr := [...]int{0,1,2,3,4,5,6,7}

	fmt.Println("arr[2:6] = ", arr[2:6])
	fmt.Println("arr[:6] = ", arr[:6])
	s1 := arr[2:6]
	fmt.Println("s1 = ", s1) //s1 =  [2 3 4 5]
	fmt.Println("arr[2:] = ", arr[2:])
	fmt.Println("arr[:] = ", arr[:])
	s2 := arr[:]
	fmt.Println("s2  = ", s2)//s2  =  [0 1 2 3 4 5 6 7]
	fmt.Println("After update slice")
	updateSlice(s1)
	updateSlice(s2)
	fmt.Println("after update slice then s1 = ", s1)//after update slice then s1 =  [100 3 4 5]
	fmt.Println("after update slice then s2 = ", s2)//after update slice then s2 =  [100 1 100 3 4 5 6 7]
	fmt.Println("the original array is arr = ", arr)//the original array is arr =  [100 1 100 3 4 5 6 7]


	fmt.Println("ReSlice")
	s2 = s2[0:2]
	fmt.Println(s2)
	s2 = s2[0:1]
	fmt.Println(s2)
}

      在切片的使用当中,遵循的是包左不包右的原则,即arr[2,6]取得是arr的2,3,4,5下标的元素。在对Slice当中的元素进行改变的时候,会直接映射到原数组的元素,如上面After update slice之后,数组arr的arr[0]元素变为了100.同时,对于Slice还可以ReSlice,即slice还可以继续slice。

三:Slice的扩展

       看如下代码:

package main

import "fmt"

//go语言当中array传递不能改变其值,而是拷贝,一般我们用切片

func updateSlice(s []int) {
	s[0] = 100
}

func main(){
	/*arr := [...]int{0,1,2,3,4,5,6,7}

	fmt.Println("arr[2:6] = ", arr[2:6])
	fmt.Println("arr[:6] = ", arr[:6])
	s1 := arr[2:6]
	fmt.Println("s1 = ", s1) //s1 =  [2 3 4 5]
	fmt.Println("arr[2:] = ", arr[2:])
	fmt.Println("arr[:] = ", arr[:])
	s2 := arr[:]
	fmt.Println("s2  = ", s2)//s2  =  [0 1 2 3 4 5 6 7]
	fmt.Println("After update slice")
	updateSlice(s1)
	updateSlice(s2)
	fmt.Println("after update slice then s1 = ", s1)//after update slice then s1 =  [100 3 4 5]
	fmt.Println("after update slice then s2 = ", s2)//after update slice then s2 =  [100 1 100 3 4 5 6 7]
	fmt.Println("the original array is arr = ", arr)//the original array is arr =  [100 1 100 3 4 5 6 7]


	fmt.Println("ReSlice")
	s2 = s2[0:2]
	fmt.Println(s2)
	s2 = s2[0:1]
	fmt.Println(s2)*/

	arr := [...]int{0,1,2,3,4,5,6,7}
	s1 := arr[2:6]
	s2 := s1[3:5]
	fmt.Println("extending slice")
	fmt.Println("s1 = ",s1)//s1 =  [2 3 4 5]
	fmt.Println("s2 = ",s2)//s2 =  [5 6]
}

      很神奇的现象是s2等于[5,6],但是s1当中却不应该有6这个元素的值的,s1也没有4这个下标索引的,但是s2却取到了,这是为什么呢?

go 语言教程(一):切片和数组

go 语言教程(一):切片和数组

     从上图可以看出,每一个slice实际上是保留了指向原数组的下标的,但是这在切片当中的索引是不可见的,例如,取s1[4]就会报错:index of range 。因此,切片是有下面几个特性的:

     1. Slice可以向后扩展,不可以向前扩展。

     2. s[i]不可以超越len(s),向后扩展不可以超越底层数组cap(s)

那么,不妨打印一下Slice的len和cap来看一下结果:

 

package main

import "fmt"

//go语言当中array传递不能改变其值,而是拷贝,一般我们用切片

func updateSlice(s []int) {
	s[0] = 100
}

func main(){
	/*arr := [...]int{0,1,2,3,4,5,6,7}

	fmt.Println("arr[2:6] = ", arr[2:6])
	fmt.Println("arr[:6] = ", arr[:6])
	s1 := arr[2:6]
	fmt.Println("s1 = ", s1) //s1 =  [2 3 4 5]
	fmt.Println("arr[2:] = ", arr[2:])
	fmt.Println("arr[:] = ", arr[:])
	s2 := arr[:]
	fmt.Println("s2  = ", s2)//s2  =  [0 1 2 3 4 5 6 7]
	fmt.Println("After update slice")
	updateSlice(s1)
	updateSlice(s2)
	fmt.Println("after update slice then s1 = ", s1)//after update slice then s1 =  [100 3 4 5]
	fmt.Println("after update slice then s2 = ", s2)//after update slice then s2 =  [100 1 100 3 4 5 6 7]
	fmt.Println("the original array is arr = ", arr)//the original array is arr =  [100 1 100 3 4 5 6 7]


	fmt.Println("ReSlice")
	s2 = s2[0:2]
	fmt.Println(s2)
	s2 = s2[0:1]
	fmt.Println(s2)*/

	arr := [...]int{0,1,2,3,4,5,6,7}
	s1 := arr[2:6]
	s2 := s1[3:5]
	fmt.Println("extending slice")
	fmt.Printf("s1 = %v, len(s1) = %d, cap(s1) = %d\n ",s1, len(s1), cap(s1))//s1 = [2 3 4 5], len(s1) = 4, cap(s1) = 6
	fmt.Printf("s2 = %v, len(s2) = %d, cap(s2) = %d\n ",s2, len(s2), cap(s2))//s2 = [5 6], len(s2) = 2, cap(s2) = 3
}

可以看见cap(s1)的值是6,cap(s2)的值是3。

四: Slice的操作

   代码如下:

package main

import "fmt"

//Slice的操作
/*
	author: lory
 */
func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	s1 := arr[2:6]
	s2 := s1[3:5]
	s3 := append(s2,10)
	s4 := append(s3,11)
	s5 := append(s4,12)
	fmt.Println("s3, s4, s5 = ", s3, s4, s5)//s3, s4, s5 =  [5 6 10] [5 6 10 11] [5 6 10 11 12]
	fmt.Println(arr)//[0 1 2 3 4 5 6 10]
}

s3,s4,s5的值没什么好奇怪的,但是arr的值只有最后一个变为了10,那是因为s2的cap是3,因此在append(s2,10)的时候arr的最后一位变为了10,又因为数组的长度是固定的,因此,在继续append的时候,go语言会对数组都进行一份拷贝为更大的数组,也就是说,s4,s5不在是对arr的view(视图)了。同时,由于append方法可能会改变数组的len和cap。得出结论是:

   1.添加元素时如果超越cap,系统会重新分配更大的底层数组。

   2.由于值传递的关系,必须接收append的返回值。s = append(slice, val)

其他的slice操作:

package main

import "fmt"

//Slice的操作
/*
	author: lory
 */
func main() {

	fmt.Println("creating slice")
	var s []int
	for i := 0; i<100 ; i++ {
		printSlice(s)
		//1.create slice
		s = append(s, 2 * i +1)
	}
	fmt.Println(s)
	//2. create slice
	s1 := []int{2,4,6,8}
	printSlice(s1)
	//3.create slice with len
	s2 := make([]int, 16)
	printSlice(s2)
	//4. create slice with len and cap
	s3 := make([]int, 12, 32)
	printSlice(s3)

	fmt.Println("Copying slice")
	copy(s2, s1)
	printSlice(s2)

	fmt.Println("Deleting element from slice")
	s2 = append(s2[:3], s2[4:]...)
	printSlice(s2)

	fmt.Println("Poping from front")
	front := s2[0]
	s2 = s2[1:]
	fmt.Println(front)
	printSlice(s2)
	fmt.Println("Poping from back")
	tail := s2[len(s2) -1]
	s2 = s2[:len(s2)-1]
	fmt.Println(tail)
	printSlice(s2)
}
func printSlice(s []int) {
	fmt.Printf("%v,len= %d, cap= %d\n", s, len(s), cap(s))
}

 

相关标签: go 切片 数组