Go语言基础四:数组和指针
GO语言中数组和指针
数组
Go语言提供了数组类型的数据结构。
数组是同一数据类型元素的集合。这里的数据类型可以是整型、字符串等任意原始的数据类型。数组中不允许混合不同类型的元素。(当然,如果是interface{}
类型数组,那么一个数组元素可以包含任意数据类型。)
数组的每一个元素都是类型相同、长度固定且已经编号的,所以数组元素可以通过索引来读取(或者修改)。索引从0开始,第一个元素的索引为0,第二个元素的索引为1,以此类推。
数组的声明
Go语言数组的声明需要指定元素类型以及元素的个数。数组是一定要声明这个size的。语法格式如下:
var array_name [Size] array_type
以上为一维 数组的定义方式。例如下面定义了数组a
的长度为10类型为int
。
var a [10] int
数组的初始化
//声明并初始化
var a = [3]int{1,2,3}
//也可以通过 := 在声明数组时快速初始化数组
a := [3]int{1,2,3}
如果数组的长度不确定,你可以使用...
来代替数组的长度,编译器会自动根据你的声明来推断数组的长度。但是要记住,使用...
代替长度,必须在声明数组的同时初始化数组。例如
var a = [3]int{1,2,3}
//或者
a := [...]int{1,2,3}
如果数组已经声明过了,可以根据数组的索引给上述数组进行初始化。例如
var a [3]int //int array with length 3
a[0] = 12 // array index starts at 0
a[1] = 13
a[2] = 14
在你没有给数组赋值或者只给个别元素赋值时,数组中所有没有被赋值的元素都被自动赋值为数组类型的零值。**上述数组中,a
是一个整型数组,所以a
的每一个元素都赋值为0。
package main
import "fmt"
func array() {
var a [3]int //int array with length 3
a[0] = 12 // array index starts at 0
fmt.Println(a)
}
上述代码的输出结果为 [12 0 0]
额外说明一下,数组的大小是类型的一部分。因此[5]int
和[25]int
是不同类型。并且数组是不能调整大小的。
数组是值类型
Go语言中,数组是值类型而不是引用类型。这意味着将数组赋值给另一个新的变量时,该变量会得到一个原始数组的副本。如果对变量进行更改,是不会影响到原始数组。
package main
import "fmt"
func main() {
a := [...]string{"hello", "world"}
b := a
b[0] = "你好"
fmt.Println("a is ", a)
fmt.Println("b is ", b)
}
上述代码中对新数组b
进行了修改,这个修改不会出现在数组a
中。程序的输出结果为
a is [hello world]
b is [你好 world]
数组的长度
通过将数组作为参数传递给len()
函数,可以得到数组的长度。
package main
import "fmt"
func main() {
a := [...]int{5, 89, 21, 78}
fmt.Println("length of a is",len(a))
}
上述程序的输出为length of a is 4
数组的迭代
for
循环
使用for
循环可以用来遍历数组的元素。
package main
import "fmt"
func array() {
a := [...]int{5, 89, 21, 78}
for i := 0; i < len(a); i++ {
fmt.Printf("数组的第%d个元素为%d ", i, a[i])
}
}
上述代码通过for
循环遍历数组的元素,从索引0
到到len(a)-1
(因为索引从0开始么)。
程序的输出结果为数组的第0个元素为5 数组的第1个元素为89 数组的第2个元素为21 数组的第3个元素为78
range
迭代数组
Go语言中提供了一种更好、更简洁的写法,就是通过for循换的range
来遍历数组。
range
关键字用于for
循环中迭代数组、切片、通道、或者集合。在数组和切片中,它返回元素的索引和对应的值,在集合中返回key-value对的ket值。
package main
import "fmt"
func array() {
for i, v := range a {//range返回元素对应的索引和值
fmt.Printf("数组的第 %d 个元素为 %d ", i, v)
}
}
如果只希望得到元素的值并忽略索引,可以通过用 _
空白标识符,替换原本用来接收索引值的变量,以此来忽略
for _, v := range a { // 忽略了索引
}
指针
指针指向内存中的特定区域并允许检索存储在其中的值。与C语言一样,可以使用运算符&
获取某个变量在内存中的地址并使用运算符*
根据地址取值。
指针的声明
一个指针变量指向了一个值的内存地址。与变量和常量类似,在使用指针前,需要声明指针。
//varName是指针变量的变量名,varType为指针类型,*号用于指定变量作为一个指针。
//*varType是指向varType类型值的指针变量类型。
var varName *varType
指针声明的示例
package main
import "fmt"
func main() {
b := 1
var a *int = &b
fmt.Printf("a的类型是%T\n",a)
fmt.Println("b的地址为",a)
}
输出结果
a的类型是*int
b的地址为 0xc000018030
Program exited.
Go中的空指针
指针的零值是nil
,如果只声明而不初始化值,那么这个其值为零值即nil
。
使用new()
函数创建指针
Go同时还提供了一个方便的函数new()
来创建指针。new()
函数将一个数据类型作为参数,并返回一个指向参数类型的指针变量。并且这个指针变量指向的值被赋为零值。
package main
import "fmt"
func main() {
//size 就是一个int型指针变量
size := new(int)
fmt.Printf("Size value is %d, type is %T, address is %v\n", *size, size, size)
*size = 85
fmt.Println("New size value is", *size)
}
解除消指针的引用
解除指针的引用就是说访问指针所指向的变量的值。例如a
为指针变量,那么解除指针引用的语法为*a
。
我们也可以根据指针来修改变量。
package main
import "fmt"
func main() {
a := 1
b := &a
c := b
fmt.Println("a的地址为:",b)
fmt.Println("a的值为:",*b)
*c++
fmt.Println("a的值为:",a)
}
输出结果
a的地址为: 0xc000018030
a的值为: 1
a的值为: 2
在上述代码中,我们首先是定义了一个整型变量a
,并将其地址赋值给指针变量b
,同时通过b
将a
的地址赋给c
。最后通过输出结果可以看到,我们可以通过指针来修改变量的值。
注意:Go语言并不支持指针运算