Go语言 | 03 数组指针切片用法

Posted “逛丢一只鞋”

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言 | 03 数组指针切片用法相关的知识,希望对你有一定的参考价值。

文章目录

Go 语言数组

Go 语言提供了数组类型的数据结构。

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。

相对于去声明 number0, number1, …, number99 的变量,使用数组形式 numbers[0], numbers[1] …, numbers[99] 更加方便且易于扩展。

数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。

声明数组

Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:

var variable_name [SIZE] variable_type

以上为一维数组的定义方式。例如以下定义了数组 balance 长度为 10 类型为 float32:

var balance [10] float32

初始化数组
以下演示了数组初始化:

var balance = [5]float321000.0, 2.0, 3.4, 7.0, 50.0

我们也可以通过字面量在声明数组的同时快速初始化数组:

balance := [5]float321000.0, 2.0, 3.4, 7.0, 50.0

如果数组长度不确定,可以使用 … 代替数组的长度,编译器会根据元素个数自行推断数组的长度:

var balance = [...]float321000.0, 2.0, 3.4, 7.0, 50.0

balance := [...]float321000.0, 2.0, 3.4, 7.0, 50.0

如果设置了数组的长度,我们还可以通过指定下标来初始化元素:

//  将索引为 1 和 3 的元素初始化
balance := [5]float321:2.0,3:7.0

初始化数组中 中的元素个数不能大于 [] 中的数字。

如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:

 balance[4] = 50.0

以上实例读取了第五个元素。数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。

访问数组元素

数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值。例如:

var salary float32 = balance[9]

以上实例读取了数组 balance 第 10 个元素的值。

以下演示了数组完整操作(声明、赋值、访问)的实例:

package main

import "fmt"

func main() 
   var n [10]int /* n 是一个长度为 10 的数组 */
   var i,j int

   /* 为数组 n 初始化元素 */        
   for i = 0; i < 10; i++ 
      n[i] = i + 100 /* 设置元素为 i + 100 */
   

   /* 输出每个数组元素的值 */
   for j = 0; j < 10; j++ 
      fmt.Printf("Element[%d] = %d\\n", j, n[j] )
   

以上实例执行结果如下:

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

初始化数组的例子

package main

import "fmt"

func main() 
   var i,j,k int
   // 声明数组的同时快速初始化数组
   balance := [5]float321000.0, 2.0, 3.4, 7.0, 50.0

   /* 输出数组元素 */         ...
   for i = 0; i < 5; i++ 
      fmt.Printf("balance[%d] = %f\\n", i, balance[i] )
   
   
   balance2 := [...]float321000.0, 2.0, 3.4, 7.0, 50.0   
   /* 输出每个数组元素的值 */
   for j = 0; j < 5; j++ 
      fmt.Printf("balance2[%d] = %f\\n", j, balance2[j] )
   

   //  将索引为 1 和 3 的元素初始化
   balance3 := [5]float321:2.0,3:7.0  
   for k = 0; k < 5; k++ 
      fmt.Printf("balance3[%d] = %f\\n", k, balance3[k] )
   

以上实例执行结果如下:

balance[0] = 1000.000000
balance[1] = 2.000000
balance[2] = 3.400000
balance[3] = 7.000000
balance[4] = 50.000000
balance2[0] = 1000.000000
balance2[1] = 2.000000
balance2[2] = 3.400000
balance2[3] = 7.000000
balance2[4] = 50.000000
balance3[0] = 0.000000
balance3[1] = 2.000000
balance3[2] = 0.000000
balance3[3] = 7.000000
balance3[4] = 0.000000

多维数组

二维数组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下:

var arrayName [ x ][ y ] variable_type
package main

import "fmt"

func main() 
    // Step 1: 创建数组
    values := [][]int

    // Step 2: 使用 append() 函数向空的二维数组添加两行一维数组
    row1 := []int1, 2, 3
    row2 := []int4, 5, 6
    values = append(values, row1)
    values = append(values, row2)

    // Step 3: 显示两行数据
    fmt.Println("Row 1")
    fmt.Println(values[0])
    fmt.Println("Row 2")
    fmt.Println(values[1])

    // Step 4: 访问第一个元素
    fmt.Println("第一个元素为:")
    fmt.Println(values[0][0])


多维数组可通过大括号来初始值。以下实例为一个 3 行 4 列的二维数组:

a := [3][4]int  
 0, 1, 2, 3 ,   /*  第一行索引为 0 */
 4, 5, 6, 7 ,   /*  第二行索引为 1 */
 8, 9, 10, 11,   /* 第三行索引为 2 */

注意:以上代码中倒数第二行的 必须要有逗号,因为最后一行的 不能单独一行,也可以写成这样:

a := [3][4]int  
 0, 1, 2, 3 ,   /*  第一行索引为 0 */
 4, 5, 6, 7 ,   /*  第二行索引为 1 */
 8, 9, 10, 11   /* 第三行索引为 2 */

Go 语言指针

Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。

接下来让我们来一步步学习 Go 语言指针。

我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。

Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

以下实例演示了变量在内存中地址:

package main

import "fmt"

func main() 
   var a int = 10  

   fmt.Printf("变量的地址: %x\\n", &a  )

执行以上代码输出结果为:

变量的地址: 20818a220

现在我们已经了解了什么是内存地址和如何去访问它。接下来我们将具体介绍指针。

如何使用指针

指针使用流程:

  • 定义指针变量。
  • 为指针变量赋值。
  • 访问指针变量中指向地址的值。

在指针类型前面加上 * 号(前缀)来获取指针所指向的内容

实例

package main

import "fmt"

func main() 
   var a int= 20   /* 声明实际变量 */
   var ip *int        /* 声明指针变量 */

   ip = &a  /* 指针变量的存储地址 */

   fmt.Printf("a 变量的地址是: %x\\n", &a  )

   /* 指针变量的存储地址 */
   fmt.Printf("ip 变量储存的指针地址: %x\\n", ip )

   /* 使用指针访问值 */
   fmt.Printf("*ip 变量的值: %d\\n", *ip )

以上实例执行输出结果为:

a 变量的地址是: 20818a220
ip 变量储存的指针地址: 20818a220
*ip 变量的值: 20

指针数组

有一种情况,我们可能需要保存数组,这样我们就需要使用到指针。

以下声明了整型指针数组:

var ptr [MAX]*int;

ptr 为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:

package main

import "fmt"

const MAX int = 3

func main() 
   a := []int10,100,200
   var i int
   var ptr [MAX]*int;

   for  i = 0; i < MAX; i++ 
      ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
   

   for  i = 0; i < MAX; i++ 
      fmt.Printf("a[%d] = %d\\n", i,*ptr[i] )
   

以上代码执行输出结果为:

a[0] = 10
a[1] = 100
a[2] = 200

指向指针的指针

如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。

当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:

指向指针的指针变量声明格式如下:

var ptr **int;

以上指向指针的指针变量为整型。

访问指向指针的指针变量值需要使用两个 * 号,如下所示:

package main

import "fmt"

func main() 

   var a int
   var ptr *int
   var pptr **int

   a = 3000

   /* 指针 ptr 地址 */
   ptr = &a

   /* 指向指针 ptr 地址 */
   pptr = &ptr

   /* 获取 pptr 的值 */
   fmt.Printf("变量 a = %d\\n", a )
   fmt.Printf("指针变量 *ptr = %d\\n", *ptr )
   fmt.Printf("指向指针的指针变量 **pptr = %d\\n", **pptr)

以上实例执行输出结果为:

变量 a = 3000
指针变量 *ptr = 3000
指向指针的指针变量 **pptr = 3000

指针作为函数参数

Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。

以下实例演示了如何向函数传递指针,并在函数调用后修改函数内的值,:

实例

package main

import "fmt"

func main() 
   /* 定义局部变量 */
   var a int = 100
   var b int= 200

   fmt.Printf("交换前 a 的值 : %d\\n", a )
   fmt.Printf("交换前 b 的值 : %d\\n", b )

   /* 调用函数用于交换值
   * &a 指向 a 变量的地址
   * &b 指向 b 变量的地址
   */
   swap(&a, &b);

   fmt.Printf("交换后 a 的值 : %d\\n", a )
   fmt.Printf("交换后 b 的值 : %d\\n", b )


func swap(x *int, y *int) 
   var temp int
   temp = *x    /* 保存 x 地址的值 */
   *x = *y      /* 将 y 赋值给 x */
   *y = temp    /* 将 temp 赋值给 y */

以上实例允许输出结果为:

交换前 a 的值 : 100
交换前 b 的值 : 200
交换后 a 的值 : 200
交换后 b 的值 : 100

Go 语言切片(Slice)

Go 语言切片是对数组的抽象。

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

定义切片

你可以声明一个未指定大小的数组来定义切片:

var identifier []type

切片不需要说明长度。

或使用 make() 函数来创建切片:

var slice1 []type = make([]type, len)

也可以简写为

slice1 := make([]type, len)

也可以指定容量,其中 capacity 为可选参数。

make([]T, length, capacity)

这里 len 是数组的长度并且也是切片的初始长度。

切片初始化

s :=[] int 1,2,3  

直接初始化切片,[] 表示是切片类型,1,2,3 初始化值依次是 1,2,3,其 cap=len=3。

s := arr[:] 

初始化切片 s,是数组 arr 的引用。

s := arr[startIndex:endIndex] 

将 arr 中从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片。

s := arr[startIndex:] 

默认 endIndex 时将表示一直到arr的最后一个元素。

s := arr[:endIndex] 

默认 startIndex 时将表示从 arr 的第一个元素开始。

s1 := s[startIndex:endIndex] 

通过切片 s 初始化切片 s1。

s :=make([]int,len,cap) 

通过内置函数 make() 初始化切片s,[]int 标识为其元素类型为 int 的切片。

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]

切片截取

可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound],实例如下:

实例

package main

import "fmt"

func main() 
   /* 创建切片 */
   numbers := []int0,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]

append() 和 copy() 函数

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

下面的代码描述了从拷贝切片的 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, 以上是关于Go语言 | 03 数组指针切片用法的主要内容,如果未能解决你的问题,请参考以下文章

Go Web编程实战----数据类型

Go Web编程实战----数据类型

Go Web编程实战----数据类型

go语言入门四(复合类型 数组切片 指针)

go语言入门四(复合类型 数组切片 指针)

Go语言切片