概述
1.數(shù)組是同一類型元素的集合侍芝。
2.數(shù)組是有固定長度的鹃锈,因此需要初始化數(shù)組是聲明長度。
3.數(shù)組屬于值類型的缚甩,即將一個(gè)數(shù)組賦值給另外一個(gè)數(shù)組的時(shí)候,實(shí)際上就是將整個(gè)數(shù)組拷貝一份窑邦。
數(shù)組的聲明
數(shù)組的聲明需要指定數(shù)量和存儲(chǔ)數(shù)據(jù)的類型擅威。其表示形式為 [n]T
。n
表示數(shù)組中元素的數(shù)量冈钦,T
代表每個(gè)元素的類型郊丛,數(shù)組一旦聲明后,其大小和類型都不能改變。
var <數(shù)組名稱> [<數(shù)組長度>]<元素類型>
eg:
package main
import (
"fmt"
)
func main() {
var a [3]int //int array with length 3
fmt.Println(a)
}
var a[3]int 聲明了一個(gè)長度為 3 的整型數(shù)組宾袜。數(shù)組中的所有元素都被自動(dòng)賦值為數(shù)組類型的零值。在這種情況下驾窟,a
是一個(gè)整型數(shù)組庆猫,因此 a
的所有元素都被賦值為 0
,即 int 型的零值绅络。運(yùn)行上述程序?qū)⑤敵?[0 0 0]
月培。
數(shù)組的索引從 0
開始到 length - 1
結(jié)束。讓我們給上面的數(shù)組賦值恩急。
package main
import (
"fmt"
)
func main() {
var a [3]int //int array with length 3
a[0] = 10 // array index starts at 0
a[1] = 20
a[2] = 50
fmt.Println(a)
//輸出 `[10 20 50]`瞎领。
}
指定元素初始化數(shù)組
var <數(shù)組名稱> = [<數(shù)組長度>]<元素類型>{元素1,元素2,...}**
package main
import (
"fmt"
)
func main() {
a := [3]int{10, 20, 50} // short hand declaration to create array
fmt.Println(a)
//輸出 `[10 20 50]`
}
在簡略聲明中樱拴,不需要將數(shù)組中所有的元素賦值。
package main
import (
"fmt"
)
func main() {
a := [3]int{12}
fmt.Println(a)
}
在上述程序中的第 8 行 a := [3]int{12}
聲明一個(gè)長度為 3 的數(shù)組,但只提供了一個(gè)值 12
墨礁,剩下的 2 個(gè)元素自動(dòng)賦值為 0
。這個(gè)程序?qū)⑤敵?code>[12 0 0]蝶俱。
省略號(hào)初始化數(shù)組
數(shù)組的長度可以使用省略號(hào) ...
代替实昨,這個(gè)并不是代表可以省略數(shù)組長度的聲明,編譯器會(huì)自動(dòng)計(jì)算數(shù)組長度窗看,它的長度值等于當(dāng)前數(shù)組初始化元素的個(gè)數(shù)茸歧。
package main
import (
"fmt"
)
func main() {
a := [...]int{12, 78, 50} // ... makes the compiler determine the length
fmt.Println(a)
}
索引初始化數(shù)組
[<數(shù)組長度>]<元素類型>{索引1:元素1,索引2:元素2,…}
const (
FIRST int = iota
SECOND
THIRD
FOURTH
)
func main() {
arr :=[4]string{FIRST:"1",SECOND:"2",THIRD:"3",FOURTH:"4"}
fmt.Println(arr)
}
//輸出[1 2 3 4]
數(shù)組比較
同樣類型的數(shù)組是可以相互賦值的,相同類型的數(shù)組必須是長度一樣显沈,并且每個(gè)元素的類型也一樣的數(shù)組软瞎,因此數(shù)組的大小是類型的一部分。因此 [5]int
和 [25]int
是不同類型拉讯。
package main
func main() {
a := [3]int{5, 78, 8}
var b [5]int
b = a // not possible since [3]int and [5]int are distinct types
}
在上述程序的第 6 行中, 我們?cè)噲D將類型 [3]int
的變量賦給類型為 [5]int
的變量涤浇,這是不允許的,因此編譯器將拋出錯(cuò)誤 main.go:6: cannot use a (type [3]int) as type [5]int in assignment遂唧。
數(shù)組是值類型
Go 中的數(shù)組是值類型而不是引用類型芙代。一個(gè)數(shù)組的變量代表著整個(gè)數(shù)組,不像其他語言指向的是數(shù)組的第一個(gè)元素盖彭,這意味著當(dāng)數(shù)組賦值給一個(gè)新的變量時(shí)纹烹,該變量會(huì)得到一個(gè)原始數(shù)組的一個(gè)副本。如果對(duì)新變量進(jìn)行更改召边,則不會(huì)影響原始數(shù)組铺呵。
package main
import "fmt"
func main() {
a := [...]string{"USA", "China", "India", "Germany", "France"}
b := a // a copy of a is assigned to b
b[0] = "Singapore"
fmt.Println("a is ", a)
fmt.Println("b is ", b)
}
在上述程序的第 7 行,a
的副本被賦給 b
隧熙。在第 8 行中片挂,b
的第一個(gè)元素改為 Singapore
。這不會(huì)在原始數(shù)組 a
中反映出來。該程序?qū)?輸出
a is [USA China India Germany France]
b is [Singapore China India Germany France]
同樣音念,當(dāng)數(shù)組作為參數(shù)傳遞給函數(shù)時(shí)沪饺,它們是按值傳遞,而原始數(shù)組保持不變闷愤。
package main
import "fmt"
func changeLocal(num [5]int) {
num[0] = 55
fmt.Println("inside function ", num)
}
func main() {
num := [...]int{5, 6, 7, 8, 8}
fmt.Println("before passing to function ", num)
changeLocal(num) //num is passed by value
fmt.Println("after passing to function ", num)
}
在上述程序的 13 行中, 數(shù)組 num
實(shí)際上是通過值傳遞給函數(shù) changeLocal
整葡,數(shù)組不會(huì)因?yàn)楹瘮?shù)調(diào)用而改變。這個(gè)程序?qū)⑤敵?
before passing to function [5 6 7 8 8]
inside function [55 6 7 8 8]
after passing to function [5 6 7 8 8]
數(shù)組的長度
通過將數(shù)組作為參數(shù)傳遞給 len
函數(shù)讥脐,可以得到數(shù)組的長度遭居。
package main
import "fmt"
func main() {
a := [...]float64{67.7, 89.8, 21, 78}
fmt.Println("length of a is",len(a))
}
上面的程序輸出為 length of a is 4
。
使用 range 迭代數(shù)組
for
循環(huán)可用于遍歷數(shù)組中的元素旬渠。
package main
import "fmt"
func main() {
a := [...]float64{67.7, 89.8, 21, 78}
for i := 0; i < len(a); i++ { // looping from 0 to the length of the array
fmt.Printf("%d th element of a is %.2f\n", i, a[i])
}
}
上面的程序使用 for
循環(huán)遍歷數(shù)組中的元素俱萍,從索引 0
到 length of the array - 1
。這個(gè)程序運(yùn)行后打印出告丢,
0 th element of a is 67.70
1 th element of a is 89.80
2 th element of a is 21.00
3 th element of a is 78.00
Go 提供了一種更好枪蘑、更簡潔的方法,通過使用 for
循環(huán)的 range 方法來遍歷數(shù)組芋齿。range
返回索引和該索引處的值腥寇。讓我們使用 range 重寫上面的代碼。我們還可以獲取數(shù)組中所有元素的總和觅捆。
package main
import "fmt"
func main() {
a := [...]float64{67.7, 89.8, 21, 78}
sum := float64(0)
for i, v := range a {//range returns both the index and value
fmt.Printf("%d the element of a is %.2f\n", i, v)
sum += v
}
fmt.Println("\nsum of all elements of a",sum)
}
上述程序的第 8 行 for i, v := range a
利用的是 for 循環(huán) range 方式赦役。 它將返回索引和該索引處的值。 我們打印這些值栅炒,并計(jì)算數(shù)組 a
中所有元素的總和掂摔。 程序的 輸出是,
0 the element of a is 67.70
1 the element of a is 89.80
2 the element of a is 21.00
3 the element of a is 78.00
sum of all elements of a 256.5
如果你只需要值并希望忽略索引赢赊,則可以通過用 _
空白標(biāo)識(shí)符替換索引來執(zhí)行乙漓。
for _, v := range a { // ignores index
}
上面的 for 循環(huán)忽略索引,同樣值也可以被忽略释移。
多維數(shù)組
到目前為止我們創(chuàng)建的數(shù)組都是一維的叭披,Go 語言可以創(chuàng)建多維數(shù)組。
package main
import (
"fmt"
)
func printarray(a [3][2]string) {
for _, v1 := range a {
for _, v2 := range v1 {
fmt.Printf("%s ", v2)
}
fmt.Printf("\n")
}
}
func main() {
a := [3][2]string{
{"lion", "tiger"},
{"cat", "dog"},
{"pigeon", "peacock"}, // this comma is necessary. The compiler will complain if you omit this comma
}
printarray(a)
var b [3][2]string
b[0][0] = "apple"
b[0][1] = "samsung"
b[1][0] = "microsoft"
b[1][1] = "google"
b[2][0] = "AT&T"
b[2][1] = "T-Mobile"
fmt.Printf("\n")
printarray(b)
}
在上述程序的第 17 行玩讳,用簡略語法聲明一個(gè)二維字符串?dāng)?shù)組 a 涩蜘。20 行末尾的逗號(hào)是必需的。這是因?yàn)楦鶕?jù) Go 語言的規(guī)則自動(dòng)插入分號(hào)熏纯。
另外一個(gè)二維數(shù)組 b 在 23 行聲明同诫,字符串通過每個(gè)索引一個(gè)一個(gè)添加。這是另一種初始化二維數(shù)組的方法樟澜。
第 7 行的 printarray 函數(shù)使用兩個(gè) range 循環(huán)來打印二維數(shù)組的內(nèi)容误窖。上述程序的 輸出是
lion tiger
cat dog
pigeon peacock
apple samsung
microsoft google
AT&T T-Mobile
這就是數(shù)組叮盘,盡管數(shù)組看上去似乎足夠靈活,但是它們具有固定長度的限制霹俺,不可能增加數(shù)組的長度柔吼。這就要用到 切片。