4.go语言数组

发布于:2025-03-29 ⋅ 阅读:(23) ⋅ 点赞:(0)

GO中的数组是一种固定长度的数据结构,用于存储同一类型的元素序列。

数组在内存中是连续存储的

数组的每个元素可以通过索引来访问,索引从0开始,最后一个元素的索引为数组长度减1

内置函数len()可以返回数组中元素的个数。

在Go中,数组是值类型。

数组声明语法

var 数组变量名 [元素数量]Type

  • 数组变量名:数组声明及使用时的变量名

  • 元素数量:数组的元素数量

  • Type:可以是任意基本类型,也可以是数组本身,类型为数组本身时,可以实现多维数组。

举个例子:创建int类型的class数组,其中元素数量为5

var class [5]int

数组的定义及赋值

var arr [5]int // 定义数组

for i := 0; i < len(arr ); i++ {

         arr[i] = i + 100 // 数组赋值

}

 fmt.Println(arr )

代码输出内容:[100 101 102 103 104]

数组的初始化

数组初始化是指在声明数组时赋值。

  • 指定长度初始化

  1. var a1 [3]int   //明确元素个数,用零值[0,0,0]填充

  2. var a2 = [3]int{}  //数组字面量定义,类型:[3]int, {}表示字面量定义。推导出a2是[0,0,0]

// {} 中的元素个数不能大于 [] 中的数字。如果小于,用零值填充,如果大于,就报错了。

  • 不指定长度初始化

当我们不指定长度的时候,也就是[]中写三个点,GO语言默认会根据元素的个数来设置数组的大小。

var students = [...]string{"zhangsan", "lisi", "wangwu", "maliu"}

  • 根据索引初始化指定元素

只初始化索引是 1和3 的元素

var students = [...]string{1: "lisi", 3: "maliu"}

二维数组

二维数组是一种由多个一维数组组成的数据结构,是数组的数组:适合大小固定的场景。

每个一维数组被称为行(row),而所有行共同构成了一个表格状的数据结构,形成了二维数组。它可以被认为是行和列的组合,类似于电子表格中的格子。

在Go语言中,二维数组可以通过指定行和列的数量来定义。例如,一个3行4列的二维数组可以这样定

var matrix [3][4]int

  • 定义和初始化二维数组需要指定行和列的数量,并为每个元素赋值。

var matrix [3][4]int

matrix[0] = [4]int{1, 2, 3, 4}

matrix[1] = [4]int{5, 6, 7, 8}

matrix[2] = [4]int{9, 10, 11, 12}

或者使用类型推导:

matrix := [3][4]int{

        {1, 2, 3, 4},

        {5, 6, 7, 8},

        {9, 10, 11, 12},

}

  • 二位数组遍历

for i := 0; i < len(matrix); i++ {

        for j := 0; j < len(matrix[i]); j++ {

                fmt.Printf("%d ", matrix[i][j])

        }

        fmt.Println()

}

注意go语言中数组不能定义为常量

注意go语言中...推导,只能用在第一维度

数组的遍历

  • 传统for循环遍历

      var arr = [...]float64{1.1, 1.2, 1.3, 1.4, 1.5, 1.6}

      for i := 0; i < len(arr); i++ {

                 fmt.Println(arr[i])

          }

  • for range循环遍历

      var arr = [...]float64{1.1, 1.2, 1.3, 1.4, 1.5, 1.6}

      for i, v := range arr {

                fmt.Printf("index=%d\tvalue=%v\n", i, v)

          }

  • 数组类型不仅是逻辑上的连续序列,而且在实际内存分配时也占据着一整块内存。Go 编译器在为数组类型的变量实际分配内存时,会为 Go 数组分配一整块、可以容纳它所有元素的连续内存

  • 数组必须在编译时就确定长度,之后不能改变长度

//错误 var a [变量]int 编译时候不能确定变量是多少,长度不确定,报错

//正确 var a [常量]int

  • 数组首地址就是数组地址

  • 元素的值可以改变,但元素地址不变。

数组是值类型

  • 两个数组类型的元素类型 T 与数组长度 N 都是一样的,那么这两个数组类型是等价的,如果有一个属性不同,它们就是两个不同的数组

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

  • [n]*T表示指针数组,*[n]T表示数组指针 。

math/rand包来生成随机数

初始化随机种子

  1. 在Go 1.20及之前的版本中,我们在生成随机数之前,

就需要使用rand.Seed(time.Now().UnixNano())初始化一下随机种子,

如果不初始化随机种子,即每次生成的随机数都一样。

  1. 在Go 1.20及之后的版本中,

如果未调用Seed,则生成器将在程序启动时生成一个随机种子。

如果需要指定Seed,请使用New(NewSource(seed))

  • rand.NewSource(seed int64) Source 创建一个新的随机数源。

  • rand.New(src Source) *Rand 使用给定的随机数源创建一个新的 Rand 实例。

seed := time.Now().UnixNano()

// 创建一个新的随机数源

src := rand.NewSource(seed)

// 使用这个随机数源创建一个新的Rand实例

r := rand.New(src)

// 生成一个随机数

num := r.Intn(100) //生成的随机数 是左闭右开区间。[0,100)实际取不到100

fmt.Printf("Random number: %d", num)

math其他函数

fmt.Scanln

Scanln 是一种用于从标准输入读取数据的函数。Scanln 它会在读取到换行符时停止并返回

Scanln 函数会根据空格自动分隔输入的数据,并将其分别存储在多个变量中。

如果 Scanln 读取失败,它会返回一个错误。你可以通过检测错误来处理

  1. func Scanln(a ...interface{}) (n int, err error)

  • a ...interface{}:这是一个可变参数,你可以传递任意数量的变量来接收输入的值。这些变量必须是能够接受输入的类型,通常是基本数据类型或它们的指针。

  • n int:返回读取的项数。

  • err error:如果在读取过程中遇到错误,将返回一个非nil的错误值

例子:

var name string = "张三"

var age int = 30

fmt.Println("请输入你的姓名和年龄,以空格分隔:")

n, err := fmt.Scanln(&name, &age)

if err == nil {

        fmt.Println(name, age, err, n)

} else {

        fmt.Println(name, age, err, n)

}

案例:根据输入数字,生成相应注数双色球:

var line string
var nums byte = 0
var rec int = 0
for rec == 0 || rec > 10 {
    fmt.Print("请输入要打印双色球的注数(1-10)")
    fmt.Scanln(&line)
    rec, _ = strconv.Atoi(line)
}
nums = byte(rec)
if nums < 1 || nums > 10 { 
    fmt.Println("系统错误,请联系开发人员@xxx")
    return
}
var num byte = 1
for ; num <= nums; num++ { 
    // ==========生成双色球开始==========
    var ssq [7]int8
    var tmp int8
    var flag bool
    for i := 0; i < 6; {
       //生成一个随机数
       tmp = int8(rand.IntN(33) + 1)
       flag = false //假设生成的tmp不和数组里的数字重复
       for j := 0; j < i; j++ {
          //判断tmp和数组里的红球是否有相等的,
          //如果有,标记flag为true,退出循环
          if tmp == ssq[j] {
             flag = true
             break
          }
       }
       //如果没有被标记为true,说明不重复,把生成的数字放到数组里,并且让循环条件加1
       if !flag {
          ssq[i] = tmp
          i++
       }
    }
    //生成蓝球。
    ssq[6] = int8(rand.IntN(16) + 1)
    fmt.Println(ssq)
    // ==========生成双色球结束==========
}