数组是一组具有相同数据类型在内存中有序存储的数据集合
特点
- 长度固定,不能修改
- 赋值和函数传递过程是值复制,涉及到内存 copy,性能低下
声明数组: var 数组名 [SIZE] 数组变量类型
var arr= [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 或者 arr:=[5]int{1,2,3,4,5}
我们也可以通过字面量在声明数组的同时快速初始化数组:
balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
如果数组长度不确定,可以使用 ... 代替数组的长度,编译器会根据元素个数自行推断数组的长度:
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 或 balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
如果设置了数组的长度,我们还可以通过指定下标来初始化元素:
// 将索引为 1 和 3 的元素初始化 balance := [5]float32{1:2.0,3:7.0}
初始化数组中 {} 中的元素个数不能大于 [] 中的数字。如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:
声明方式:var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
初始化二维数组:
- a := [3][4]int{
- {0, 1, 2, 3} , /* 第一行索引为 0 */
- {4, 5, 6, 7} , /* 第二行索引为 1 */
- {8, 9, 10, 11}, /* 第三行索引为 2 */
-
- //注意:以上代码中倒数第二行的 } 必须要有逗号,因为最后一行的 } 不能单独一行,也可以写成这样:
- }
- a := [3][4]int{
- {0, 1, 2, 3} , /* 第一行索引为 0 */
- {4, 5, 6, 7} , /* 第二行索引为 1 */
- {8, 9, 10, 11}} /* 第三行索引为 2 */
go语言还支持创建元素数量不一致的多维数组
- package main
-
- import "fmt"
-
- func main() {
- // 创建空的二维数组
- animals := [][]string{}
-
- // 创建三一维数组,各数组长度不同
- row1 := []string{"fish", "shark", "eel"}
- row2 := []string{"bird"}
- row3 := []string{"lizard", "salamander"}
-
- // 使用 append() 函数将一维数组添加到二维数组中
- animals = append(animals, row1)
- animals = append(animals, row2)
- animals = append(animals, row3)
-
- // 循环输出
- for i := range animals {
- fmt.Printf("Row: %v\n", i)
- fmt.Println(animals[i])
- }
- }
切片(slice)是一组具有相同数据类型在内存中有序存储的可扩容的数据集合
- var 切片名 []数据类型
- var slice []int
- make([]数据类型,长度)
- var slice []int = make([]int, 10)
当使用var slice []int 是此时的切片实际上是一个nil,还没有被开辟空间,只是有了一个slice的“引用”。而使用make的方式时会为我们的slice开辟你传入的大小的空间。
func main() { var slice []int slice[0] = 123 fmt.Println(slice) }上面的代码是一个错误的代码 在运行的时候会报错越界问题。
我们可以通过len() 和cap()函数来求取我们的slice的长度和容量(长度就是我们当前slice中存了多少了元素,而容量是slice最大可以容纳的元素数量。)
在go源码中当length小于1024的时候是按照2倍来扩容的,当超过1024的时候每次是以前的1.25倍。
- func main() {
- /*var slice []int
- slice[0] = 123
- fmt.Println(slice)*/
-
- var s1 = make([]int, 2)
- //slice自动扩容
- s1 = append(s1, 1)
- s1 = append(s1, 2)
- s1 = append(s1, 1)
- s1 = append(s1, 1)
- fmt.Printf("%v\n", s1)
- //现在我们来查看len cap
- println(len(s1)) //6 0 0 1 2 1 1
- println(cap(s1)) //8
- }
切片在截取的时候返回的新的切片是指向原来的切片的内存地址的。感觉类似于浅拷贝,改变截取后的切片的值也会同步的改变原切片的值。
- func main() {
- //切片的截取
- slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
-
- //切片名[起始下标:结束下标:容量] 左闭右开 包含起始下标 不包含结束下标
- //s := slice[2:7]
- //fmt.Println(s)
- //s:=slice[2:]
- //fmt.Println(s)
- //s:=slice[:5]
- //fmt.Println(s)
- s := slice[2:5:6] //实际容量=容量-起始下标
- fmt.Println(s)
- //fmt.Println(len(s))
- //fmt.Println(cap(s))
- s[0] = 333
- //切片的截取 是将新的切片指向源切片的内存地址 修改一个会影响另外一个
- fmt.Println(s)
- fmt.Println(slice)
-
- fmt.Println(unsafe.Sizeof(slice))
- fmt.Println(unsafe.Sizeof(s))
- }
利用切片的属性还可以简单的实现一个CRUD
- func test6() {
- //slice crud
-
- var nums = []int{1, 2, 3, 4, 5}
- fmt.Printf("nums = %v\n", nums)
- //新增
- nums = append(nums, 6)
- fmt.Printf("新增后nums = %v\n", nums)
- //删除
- //比如删除我们切片中的下表为2的元素
- s1 := append(nums[:2], nums[3:]...)
- fmt.Printf("删除后nums = %v\n", s1)
- //改
- nums[2] = 222
- fmt.Printf("修改后nums = %v\n", nums)
- //查找
- //给定一个key 查找下标然后返回 找不到返回-1
- var key = 3
- for i, num := range nums {
- if num == key {
- fmt.Printf("找到%d了,下表为%d:", key, i)
- }
- }
-
- }
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
- m1 := map[string]string{
- "name": "zhangsan",
- "age": "22",
- }
- fmt.Println(m1)
-
- m2 := make(map[string]int) //m2 == empty map
-
- var m3 map[string]int //m3 == nil
-
- fmt.Print(m2, m3)
-
- fmt.Print("遍历...\n")
- for i, v := range m1 {
- fmt.Println(i, v)
- }
- name := m1["name"]
- fmt.Println(name)
- //可以返回一个ok值 判断我们的key是否正确
- nema, ok := m1["nema"] //找不到这个键 就会返回false
- fmt.Print(nema, ok)
- //所以可以改进代码
- if name, ok := m1["name"]; ok == true {
- fmt.Println(name)
- }
只要将数据存储在内存中都会为其分配内存地址。内存地址使用十六进数据表示。内存为每一个字节分配一个 32 位或 64 位的编号(与 32 位或者 64 位处理器相关)。可以使用运算符 & (取地址运算符)来获取数据的内存地址。
- func main() {
- a := 10
- //取出变量a在内存的地址
- //fmt.Println(&a)
- var p *int = &a
- //fmt.Println(p)
- //fmt.Println(&a)
- //通过指针间接修改变量的值
- *p = 132
- fmt.Println(a)
-
- //const MAX int = 100
- //fmt.Println(&MAX)//err 不可以获取常量的内存地址
- }
- func main() {
- //定义指针 默认值为nil 指向内存地址编号为0的空间 内存地址0-255为系统占用 不允许用户读写操作
- //var p *int = nil
- //*p = 123 //err
- //fmt.Println(*p)
-
- //开辟数据类型大小的空间 返回值为指针类型
- //new(数据类型)
- var p *int
- p = new(int)
- *p = 123
- fmt.Println(*p)
- }