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]
数组的初始化
数组初始化是指在声明数组时赋值。
指定长度初始化
var a1 [3]int //明确元素个数,用零值[0,0,0]填充
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
包来生成随机数
初始化随机种子
在Go 1.20及之前的版本中,我们在生成随机数之前,
就需要使用rand.Seed(time.Now().UnixNano())
初始化一下随机种子,
如果不初始化随机种子,即每次生成的随机数都一样。
在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
读取失败,它会返回一个错误。你可以通过检测错误来处理
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)
// ==========生成双色球结束==========
}