100天精通Golang(基础入门篇)——第10天:Go语言中的数组

简介: 100天精通Golang(基础入门篇)——第10天:Go语言中的数组

🌷 博主 libin9iOak带您 Go to Golang Language.✨

🦄 个人主页——libin9iOak的博客🎐
🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐
🪁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🐥



摘要

本篇文章是100天"学习Golang"系列文章的第10篇,主要介绍了Go语言中的数组以及数组的语法、多维数组、数组是值类型等内容。通过阅读本篇文章,读者能够了解到如何在Go语言中定义和使用数组,并掌握一些实用的代码技巧。

前言

Go语言是一种现代的、快速、并发的编程语言,由于其简单的语法和高效的执行效率,越来越受到广大开发者的青睐。本篇文章是100天学习Golang的第一篇,旨在为初学者提供一份关于Go语言数组的基础入门指南。我们将从数组的定义开始,详细介绍各种语法和技巧,帮助读者快速掌握Go语言数组的基础知识。

Go语言中的数组

本篇文章介绍了Go语言中的数组,包括数组的定义、多维数组、数组的访问和值类型等知识点。掌握这些知识对于进一步学习Go语言非常重要。

一、数组(Array)

在Go语言中,数组(Array)是一种基本的数据结构,用于存储一组固定长度的同种数据类型的数据。数组中每个元素在内存中都是连续存储的。

1.1 什么是数组

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

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

数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为 0,第二个索引为 1,以此类推。数组的下标取值范围是从0开始,到长度减1。

数组一旦定义后,大小不能更改。

数组是一组相同类型对象的集合,每个对象的类型和大小都相同。数组是一种顺序存储结构,因此数组中的元素可以随机访问,数组的下标从0开始,逐个增加。

数组具有以下特点:

  • 数组长度是固定的,不能动态变化。
  • 数组中每个元素的类型和大小都相同。
  • 数组中的元素在内存中是连续存储的,可以随机访问。
  • 数组是值类型,传递时复制整个数组。

1.2 数组的语法

定义一个数组需要指定其元素的类型和长度,在Go语言中的数组定义语法如下:

var 数组名 [元素个数]T

其中,T表示元素的类型,数组名表示数组的名称,元素个数表示数组的长度,长度必须是一个常量表达式。

例如:

var arr [5]int //定义一个长度为5,元素类型为int的数组

可以通过下标访问数组中的元素,下标从0开始,例如:

arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5

取数组的长度可以使用len()函数,例如:

length := len(arr) // length等于5

声明和初始化数组

需要指明数组的大小和存储的数据类型。

var variable_name [SIZE] variable_type

示例代码:

var balance [10] float32
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

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

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

var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}
balance[4] = 50.0

数组的其他创建方式:

var a [4] float32 // 等价于:var arr2 = [4]float32{}
  fmt.Println(a) // [0 0 0 0]
  var b = [5] string{"ruby", "王二", "rose"}
  fmt.Println(b) // [ruby 王二 rose  ]
  var c = [5] int{'A', 'B', 'C', 'D', 'E'} // byte
  fmt.Println(c) // [65 66 67 68 69]
  d := [...] int{1,2,3,4,5}// 根据元素的个数,设置数组的大小
  fmt.Println(d)//[1 2 3 4 5]
  e := [5] int{4: 100} // [0 0 0 0 100]
  fmt.Println(e)
  f := [...] int{0: 1, 4: 1, 9: 1} // [1 0 0 0 1 0 0 0 0 1]
  fmt.Println(f)

访问数组元素

float32 salary = balance[9]

示例代码:

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

数组的长度

通过将数组作为参数传递给len函数,可以获得数组的长度。

示例代码:

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

您甚至可以忽略声明中数组的长度并将其替换为…让编译器为你找到长度。这是在下面的程序中完成的。

示例代码:

package main
import (  
    "fmt"
)
func main() {  
    a := [...]int{12, 78, 50} // ... makes the compiler determine the length
    fmt.Println(a)
}

遍历数组:

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

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

如果您只需要值并希望忽略索引,那么可以通过使用_ blank标识符替换索引来实现这一点。

for _, v := range a { //ignores index  
}

1.2 代码案例1

package main
import "fmt"
func main() {
  /*
    数据类型:
      基本类型:整数,浮点,布尔,字符串
      复合类型:array,slice,map,struct,pointer,function,channel。。。
    数组:
      1.概念:存储一组相同数据类型的数据结构
          理解为容器,存储一组数据
      2.语法:
          var 数组名 [长度] 数据类型
          var 数组名 = [长度] 数据类型{元素1,元素2.。。}
          数组名 := [...]数据类型{元素。。。}
      3.通过下标访问
        下标,也叫索引:index,
        默认从0开始的整数,直到长度减1
        数组名[index]
          赋值
          取值
        不能越界:[0,长度-1]
      4.长度和容量:go语言的内置函数
        len(array/map/slice/string),长度
        cap(),容量
  */
  var num1 int
  num1 = 100
  num1 = 200
  fmt.Println(num1)
  fmt.Printf("%p\n", &num1)
  //step1:创建数组
  var arr1 [4]int
  fmt.Printf("%p\n", &arr1)
  //step2:数组的访问
  arr1[0] = 1
  arr1[1] = 2
  arr1[2] = 3
  arr1[3] = 4
  fmt.Println(arr1[0]) //打印第一个数值
  fmt.Println(arr1[2]) //打印第三个数值
  //fmt.Println(arr1[4]) //invalid array index 4 (out of bounds for 4-element array)
  fmt.Println("数组的长度:", len(arr1)) //容器中实际存储的数据量
  fmt.Println("数组的容量:", cap(arr1)) //容器中能够存储的最大的数量
  //因为数组定长,长度和容量相同
  arr1[0] = 100
  fmt.Println(arr1[0])
  //数组的其他创建方式
  var a [4]int //同 var a= [4] int
  fmt.Println(a)
  var b = [4]int{1, 2, 3, 4}
  fmt.Println(b)
  var c = [5]int{1, 2, 4}
  fmt.Println(c)
  var d = [5]int{1: 1, 3: 2}
  fmt.Println(d)
  var e = [5]string{"rose", "王二", "ruby"}
  fmt.Println(e)
  f := [...]int{1, 2, 3, 4, 5}
  fmt.Println(f)
  fmt.Println(len(f))
  g := [...]int{1: 3, 6: 5}
  fmt.Println(g)
  fmt.Println(len(g))
}

运行结果:

200
0xc0000a6058
0xc0000d0040
1
3
数组的长度: 4
数组的容量: 4
100
[0 0 0 0]
[1 2 3 4]
[1 2 4 0 0]
[0 1 0 2 0]
[rose 王二 ruby  ]
[1 2 3 4 5]
5
[0 3 0 0 0 0 5]
7
进程 已完成,退出代码为 0

截图:

1.2 代码案例2 array_for_range

代码案例:

package main
import "fmt"
func main() {
  /*
    数组的遍历:
      依次访问数组中的元素
      方法一:arr[0],arr[1],arr[2]....
      方法二:通过循环,配合下标
        for i:=0;i<len(arr);i++{
          arr[i]
        }
      方法三:使用range
        range,词义"范围"
        不需要操作数组的下标,到达数组的末尾,自动结束for range循环。
          每次都数组中获取下标和对应的数值。
  */
  arr1 := [5]int{1, 2, 3, 4, 5}
  fmt.Println(arr1[0])
  fmt.Println(arr1[1])
  fmt.Println(arr1[2])
  fmt.Println(arr1[3])
  fmt.Println(arr1[4])
  fmt.Println("---------------")
  for i := 0; i < len(arr1); i++ {
    arr1[i] = i*2 + 1
    fmt.Println(arr1[i])
  }
  fmt.Println(arr1)
  fmt.Println("----------------")
  for index, value := range arr1 {
    fmt.Printf("下标是:%d,数值是:%d\n", index, value)
  }
  sum := 0
  for _, v := range arr1 {
    sum += v
  }
  fmt.Println(sum)
}

运行结果:

GOROOT=D:\Go #gosetup
GOPATH=C:\Users\DELL\go #gosetup
D:\Go\bin\go.exe build -o C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day10_Array__1_.exe D:\GolandProjects\Day10-Array\array_for_range.go #gosetup
C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_Day10_Array__1_.exe
1
2
3
4
5
---------------
1
3
5
7
9
[1 3 5 7 9]
----------------
下标是:0,数值是:1
下标是:1,数值是:3
下标是:2,数值是:5
下标是:3,数值是:7
下标是:4,数值是:9
25
进程 已完成,退出代码为 0

运行截图:

1.3 多维数组

在Go语言中,可以定义多维数组,例如定义一个二维数组:

var arr [3][4]int

其中,第一个方括号表示行数,第二个方括号表示列数,也可以使用初始化列表的方式进行初始化,例如:

arr := [3][4]int{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}

可以通过下标访问多维数组中的元素,例如:

arr[1][2] = 7

Go 语言支持多维数组,以下为常用的多维数组声明语法方式:

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
var threedim [5][10][4]int

三维数组

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

1.3 代码案例1

package main
import "fmt"
func main() {
  /*
    一维数组:存储的多个数据是数值本身
      a1 :=[3]int{1,2,3}
    二维数组:存储的是一维的一维
      a2 := [3][4]int{{},{},{}}
      该二维数组的长度,就是3。
      存储的元素是一维数组,一维数组的元素是数值,每个一维数组长度为4。
    多维数组:。。。
  */
  a2 := [3][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}
  fmt.Println(a2)
  fmt.Printf("二维数组的地址:%p\n", &a2)
  fmt.Printf("二维数组的长度:%d\n", len(a2))
  fmt.Printf("一维数组的长度:%d\n", len(a2[0]))
  fmt.Println(a2[0][3]) // 4
  fmt.Println(a2[1][2]) //7
  fmt.Println(a2[2][1]) // 10
  //遍历二维数组
  for i := 0; i < len(a2); i++ {
    for j := 0; j < len(a2[i]); j++ {
      fmt.Print(a2[i][j], "\t")
    }
    fmt.Println()
  }
  fmt.Println("---------------------")
  //for range 遍历二维数组
  for _, arr := range a2 {
    for _, val := range arr {
      fmt.Print(val, "\t")
    }
    fmt.Println()
  }
}

运行结果:

C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___1go_build_Day10_Array.exe
[[1 2 3 4] [5 6 7 8] [9 10 11 12]]
二维数组的地址:0xc000086120
二维数组的长度:3
一维数组的长度:4
4
7
10
1       2       3       4
5       6       7       8
9       10      11      12
---------------------
1       2       3       4
5       6       7       8
9       10      11      12
进程 已完成,退出代码为 0

运行截图:

1.4 数组是值类型

数组是值类型

Go中的数组是值类型,而不是引用类型。这意味着当它们被分配给一个新变量时,将把原始数组的副本分配给新变量。如果对新变量进行了更改,则不会在原始数组中反映。

在Go语言中,数组是值类型,意味着当数组被传递给函数时,整个数组会被复制,而不是传递数组的指针。因此,如果要修改函数中的数组,必须使用指针。

例如:

func modifyArray(arr [5]int) {
    arr[0] = 10
    fmt.Println("arr inside function:", arr)
}
func main() {
    arr := [5]int{1,2,3,4,5}
    modifyArray(arr)
    fmt.Println("arr outside function:", arr)
}

以上代码中输出如下:

arr inside function: [10 2 3 4 5]
arr outside function: [1 2 3 4 5]

代码案例2:

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

运行结果:

a is [USA China India Germany France]  
b is [Singapore China India Germany France]

数组的大小是类型的一部分。因此[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
}

1.4代码案例

代码案例:

package main
import "fmt"
func main() {
  /*
    数据类型:
      基本类型:int,float,string,bool。。
      复合类型:array,slice,map,function,pointer,channel。。
    数组的数据类型:
      [size]type
    值类型:理解为存储的数值本身
      将数据传递给其他的变量,传递的是数据的副本(备份)
        int,float,string,bool,array
    引用类型:理解为存储的数据的内存地址
        slice,map。。
  */
  //1.数据类型
  num := 10
  fmt.Printf("%T\n", num)
  arr1 := [4]int{1, 2, 3, 4}
  arr2 := [3]float64{2.15, 3.18, 6.19}
  arr3 := [4]int{5, 6, 7, 8}
  arr4 := [2]string{"hello", "world"}
  fmt.Printf("%T\n", arr1) //[4]int
  fmt.Printf("%T\n", arr2) //[3]float64
  fmt.Printf("%T\n", arr3) //[4]int
  fmt.Printf("%T\n", arr4) //[2]string
  //2.赋值
  num2 := num            //值传递
  fmt.Println(num, num2) //10 10
  num2 = 20
  fmt.Println(num, num2) //10 20
  //数组呢
  arr5 := arr1 //值传递
  fmt.Println(arr1)
  fmt.Println(arr5)
  arr5[0] = 1
  fmt.Println(arr1)
  fmt.Println(arr5)
  a := 3
  b := 4
  fmt.Println(a == b)       //比较a和b的数值是否相等
  fmt.Println(arr5 == arr1) //比较数组的对应下标位置的数值是否相等
  //fmt.Println(arr1 == arr2) //invalid operation: arr1 == arr2 (mismatched types [4]int and [3]float64)
}

运行结果:

GOROOT=D:\Go #gosetup
GOPATH=C:\Users\DELL\go #gosetup
D:\Go\bin\go.exe build -o C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_array_type_go.exe D:\GolandProjects\Day10-Array\array_type.go #gosetup
C:\Users\DELL\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_array_type_go.exe
int
[4]int
[3]float64
[4]int
[2]string
10 10
10 20
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]
false
true
进程 已完成,退出代码为 0

运行截图:

今日学习总结

本篇文章主要介绍了Go语言中的数组,包括数组的定义、语法、多维数组、数组是值类型等方面的内容。通过阅读本篇文章,读者可以深入了解Go语言数组的基础知识,并掌握一些实用技巧。总体而言,本篇文章对于初学者非常友好,详细讲解了数组在Go语言中的应用,帮助读者更好地理解并熟练使用Go语言数组。

结语

通过今天的学习,您已经踏上了Golang的学习之旅。在未来的日子里,您将探索Golang的各个方面,从基础概念到高级技巧,从实际应用到性能优化。

学习一门编程语言是一个持续的过程,每一天都是您向Golang的精通迈进的重要一步。我鼓励您坚持每天学习,保持热情和好奇心,解决挑战并享受成功的喜悦。

在您的学习旅程中,不要忘记参与社区和与其他Golang开发者交流。分享您的见解和经验,向他人学习,并在开源项目或实际应用中展示您的技能。

如果您在学习过程中遇到困难或有任何问题,不要犹豫向社区和专家寻求帮助。持续学习,勇敢探索,您将在Golang领域取得令人瞩目的成就。

最后,感谢您的阅读和支持!祝愿您在未来的每一天中都能够成为一名精通Golang的开发者!

期待听到您在学习过程中的进展和成就。如果您需要进一步的帮助,请随时告诉我。祝您在学习Golang的旅程中取得巨大成功!

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

如果您在学习过程中有任何疑惑,请点击下方名片,带您一对一快速入门 Go语言 的世界 ~

目录
相关文章
|
29天前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
39 7
|
3月前
|
存储 前端开发 Go
Go语言中的数组
在 Go 语言中,数组是一种固定长度的、相同类型元素的序列。数组声明时长度已确定,不可改变,支持多种初始化方式,如使用 `var` 关键字、短变量声明、省略号 `...` 推断长度等。数组内存布局连续,可通过索引高效访问。遍历数组常用 `for` 循环和 `range` 关键字。
|
28天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
104 67
|
4月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
120 3
Golang语言之gRPC程序设计示例
|
2月前
|
JSON Go 开发者
go-carbon v2.5.0 发布,轻量级、语义化、对开发者友好的 golang 时间处理库
carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,提供了对时间穿越、时间差值、时间极值、时间判断、星座、星座、农历、儒略日 / 简化儒略日、波斯历 / 伊朗历的支持。
41 4
|
2月前
|
存储 Cloud Native Shell
go库介绍:Golang中的Viper库
Viper 是 Golang 中的一个强大配置管理库,支持环境变量、命令行参数、远程配置等多种配置来源。本文详细介绍了 Viper 的核心特点、应用场景及使用方法,并通过示例展示了其强大功能。无论是简单的 CLI 工具还是复杂的分布式系统,Viper 都能提供优雅的配置管理方案。
|
2月前
|
Unix Linux Go
go进阶编程:Golang中的文件与文件夹操作指南
本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
|
2月前
|
Java Go 数据处理
go语言使用切片而非数组
【10月更文挑战第18天】
16 1
|
4月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
83 3
Golang语言之Prometheus的日志模块使用案例
|
3月前
|
前端开发 中间件 Go
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
49 0