Golang基础之数组 转

1 数组介绍

数组是同一类型元素的集合。例如,整数集合 5,8,9,79,76 形成一个数组。Go 语言中不允许混合不同类型的元素,例如包含字符串和整数的数组。(注:当然,如果是 interface{} 类型数组,可以包含任意类型) 。

2 数组常见操作

一个数组的表示形式为 [n]T。n 表示数组中元素的数量,T 代表每个元素的类型。元素的数量 n 也是该类型的一部分 。

2.1 数组初始化

一维数组初始化如下

func main() {     var a [4]int    //元素自动初始化为零[0 0 0 0]     b := [4]int{2, 5}  //未提供初始化值得元素自动初始化为0  [2 5 0 0]     c := [4]int{5, 3: 10} //可指定索引位置初始化 [5 0 0 10]     d := [...]int{1, 2, 3} //编译器按初始化值数量确定数组长度 [1 2 3]     e := [...]int{10, 3: 100} //支持索引初始化,但注意数组长度与此有关 [10 0 0 100]     fmt.Println(a, b, c, d, e) } 对于结构等复合类型,可省略元素初始化类型标签

package main

import "fmt"

func main() {     type user struct {         name string         age  byte     }

    d := [...]user{         {"tom", 20},// 可省略元素类型。         {"lee", 18},// 别忘了最后一行的逗号。     }

    fmt.Printf("%#v\n", d) } /*output [2]main.user{main.user{name:"tom", age:0x14}, main.user{name:"lee", age:0x12}} */ 在定义多维数组时,仅第一维度允许使用“…”

package main

import "fmt"

func main() {     a := [2][2]int{         {1, 2},         {3, 4},     }

    b := [...][2]int{         {10, 20},         {30, 40},     }

    c := [...][2][2]int{   //三维数组         {             {1, 2},             {3, 4},         },         {             {10, 20},             {30, 40},         },     }

    fmt.Println(a)  //[[1 2] [3 4]]     fmt.Println(b)  //[[10 20] [30 40]]     fmt.Println(c)  //[[[1 2] [3 4]] [[10 20] [30 40]]] } 多维数组定义

package main

import (     "fmt" )

var arr0 [5][3]int var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}

func main() {     a := [2][3]int{{1, 2, 3}, {4, 5, 6}}     b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。     fmt.Println(arr0, arr1)     fmt.Println(a, b) }

/* output [[0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0]] [[1 2 3] [7 8 9]] [[1 2 3] [4 5 6]] [[1 1] [2 2] [3 3]]  */ 2.2 数组索引

数组的索引从 0 开始到 length - 1 结束

func main() {     var a [3]int //int array with length 3     a[0] = 12    // array index starts at 0     a[1] = 78     a[2] = 50     fmt.Println(a) } 2.3 数组是值类型

Go 中的数组是值类型而不是引用类型。这意味着当数组赋值给一个新的变量时,该变量会得到一个原始数组的一个副本。如果对新变量进行更改,则不会影响原始数组。

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)  //a is  [USA China India Germany France]     fmt.Println("b is ", b)  //b is  [Singapore China India Germany France] } 上述程序中,a 的副本被赋给 b。在第 4 行中,b 的第一个元素改为 Singapore。这不会在原始数组 a 中反映出来。

同样,当数组作为参数传递给函数时,它们是按值传递,而原始数组保持不变。

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) }

/*output 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] */ 在上述程序的 13 行中, 数组 num 实际上是通过值传递给函数 changeLocal,数组不会因为函数调用而改变。

值拷贝行为会造成性能问题,通常会建议使用 slice,或数组指针。

package main

import (     "fmt" )

func test(x [2]int) {     fmt.Printf("x: %p\n", &x)     x[1] = 1000 } func main() {     a := [2]int{}     fmt.Printf("a: %p\n", &a)     test(a)     fmt.Println(a) } /* output: a: 0xc042062080 x: 0xc0420620c0 [0 0]  */ 2.4 数组长度和元素数量

通过将数组作为参数传递给 len 函数,可以得到数组的长度。 cap可以得到元素数量

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     fmt.Println("num of a is",cap(a)) //num of a is 4 } 注意:内置函数len和cap都返回第一维度长度

package main

func main() {     a := [2]int{}     b := [...][2]int{         {10, 20},         {30, 40},         {50, 60},     }

    println(len(a), cap(a))   // 2 2     println(len(b), cap(b))   // 3 3     println(len(b[1]), cap(b[1]))  // 2 2 } 2.5 使用 range 迭代数组

for 循环可用于遍历数组中的元素。

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 循环遍历数组中的元素,从索引 0 到 length of the array - 1

Go 提供了一种更好、更简洁的方法,通过使用 for 循环的 range 方法来遍历数组。range返回索引和该索引处的值。让我们使用 range 重写上面的代码。我们还可以获取数组中所有元素的总和。

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 循环 range 方式。 它将返回索引和该索引处的值。 我们打印这些值,并计算数组 a 中所有元素的总和。

如果你只需要值并希望忽略索引,则可以通过用 _ 空白标识符替换索引来执行。

for _, v := range a { // ignores index  } 1 上面的 for 循环忽略索引,同样值也可以被忽略。

2.6 数组操作符操作

如元素类型支持”==,!=”操作符,那么数组也支持此操作

package main

func main() {     var a, b [2]int     println(a == b)  //true

    c := [2]int{1, 2}     d := [2]int{0, 1}     println(c != d) //true     /*         var e, f [2]map[string]int         println(e == f)  //invalid operation: e == f ([2]map[string]int cannot be compared)     */ } 3 数组高级用法

3.1 多维数组

到目前为止我们创建的数组都是一维的,Go 语言可以创建多维数组。

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) }

/*output lion tiger  cat dog  pigeon peacock 

apple samsung  microsoft google  AT&T T-Mobile  */ 多维数组遍历

package main

import (     "fmt" )

func main() {     var f [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}     for k1, v1 := range f {         for k2, v2 := range v1 {             fmt.Printf("(%d,%d)=%d ", k1, k2, v2)         }         fmt.Println()     } } /* output: (0,0)=1 (0,1)=2 (0,2)=3  (1,0)=7 (1,1)=8 (1,2)=9   */ 3.2 数组指针和指针数组

要分清指针数组和数组指针的区别。指针数组是指元素为指针类型的数组,数组指针是获取数组变量的地址。

package main

import "fmt"

func main() {     x, y := 10, 20     a := [...]*int{&x, &y}     p := &a

    fmt.Printf("%T,%v\n", a, a)  //[2]*int,[0xc042062080 0xc042062088]     fmt.Printf("%T,%v\n", p, p)  //*[2]*int,&[0xc042062080 0xc042062088] } 可获取任意元素地址

func main() {     a := [...]int{1, 2}     println(&a, &a[0], &a[1])  //0xc042049f68 0xc042049f68 0xc042049f70 } 数组指针可以直接用来操作元素

func main() {     a := [...]int{1, 2}     p := &a

    p[1] += 10     println(p[1])   //12 } 4 数组使用常见坑

定义数组类型时,数组长度必须是非负整型常量表达式,长度是类型组成部分。也就是说,元素类型相同,但长度不同的数组不属于同一类型。

例子:

func main() {     var d1 [3]int     var d2 [2]int     d1 = d2 //cannot use d2 (type [2]int) as type [3]int in assignment } 5 数组总结

数组:是同一种数据类型的固定长度的序列。

数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。

长度是数组类型的一部分,因此,var a[5] int和var a[10]int是不同的类型。

数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1。数组索引常用操作如下:

for i := 0; i < len(a); i++ {    ... } 

for index, v := range a {    ... }  访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic

数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。

支持 “==”、”!=” 操作符,因为内存总是被初始化过的。

指针数组 [n]*T,数组指针*[n]T。

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Pulsar-V

WMI-Win32_VideoController 显卡参数

AcceleratorCapabilities --图形和视频控制器的三维阵列的能力 AdapterCompatibility --用于此控制器与系统比较...

18310
来自专栏LeetCode

java基础

当一个线程需要调用对象的wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的notify()方...

11900
来自专栏我叫刘半仙

从源码角度理解Java设计模式——责任链模式

适用场景(核心):只要把你的请求抛给第一个处理者,不用关心谁处理的,并且最终会返回你一个结果。

20510
来自专栏一丘一壑

Genesis框架从入门到精通(8): 框架过滤器和数组

Genesis Explained Framework Filters with Arrays

10120
来自专栏星汉技术

Maven常用命令 原

说到命令,则不得不提一下环境变量,在之前的博文中简单提了一下环境变量的配置,这里具体说一下。说完环境变量的配置,然后就是Maven的常用命令,这里说的是常用的几...

18720
来自专栏林德熙的博客

C# BBcode 转 Markdown

本文的方法都是使用正则转换,现在支持的代码只有很少的常用标签,如果大家发现有转换失败的,请帮我修改代码,估计代码我不会进行修改。

9620
来自专栏星汉技术

Java API:String class 原

上面由API提供的描述,可以看出,String是一个最终类,继承了Object类,实现了序列化接口和排序接口以及char可读序列接口。可以得出以下几个特点。

26220
来自专栏开发经验记录

机器学习:数据预处理之独热编码(One-Hot)

在机器学习算法中,我们经常会遇到分类特征,例如:人的性别有男女,祖国有中国,美国,法国等。 这些特征值并不是连续的,而是离散的,无序的。通常我们需要对其进行特...

16710
来自专栏Pulsar-V

WMI-Win32_PhysicalMemory 内存条参数

uint64 Capacity --获取内存容量(单位KB) string Caption --物理内存还虚拟内存 uint32 Conf...

33520
来自专栏我叫刘半仙

从源码角度理解Java设计模式——装饰者模式

优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个功能按想要的顺序执行,以实现不同效果。

17130

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励