社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
数组可以存放多个同一类型数据。数组也是一种数据类型,在 Go 中,数组是值类型。
package main
import "fmt"
func main() {
var hen [6]float64
hen[0] = 1.00
hen[1] = 1.00
hen[2] = 2.00
hen[3] = 3.00
hen[4] = 4.00
hen[5] = 50.00
var sum float64
for i := 0; i < len(hen); i++ {
sum += hen[i]
}
/**
sum / float64(len(hen)) 这里之所以强转,是因为 len 是有数据类型的, 为 int
如果直接写常量 6 就不需要
*/
average := fmt.Sprintf("%.2f", sum / float64(len(hen)))
fmt.Println("average = ", average)
}
数组定义和内存布局
var 数组名[数组大小]数据类型
var a (5]int
赋初值
a[0]= 1
a[1]=30…
对上图的总结:
四种初始化
package main
import "fmt"
func main() {
var arr1 [3]int = [3]int {0, 1, 2}
fmt.Println("arr1 = ", arr1)
var arr2 = [3]int {0, 1, 2}
fmt.Println("arr2 = ", arr2)
var arr3 = [...]int {0, 1, 2}
fmt.Println("arr3 = ", arr3)
var arr4 = [...]int {2: 900, 1: 800, 0:222}
fmt.Println("arr4 = ", arr4)
}
数组的遍历
for index, value := range array {
}
如果 index 没有用到,可以使用 _ 忽略
var arr = [...]int {2: 900, 1: 800, 0:222}
for value,index := range arr {
fmt.Printf("value = %v, index = %vn", value, index)
}
数组使用注意事项和细节
数值类型数组:默认值为 0
字符串数组:默认值为 “”
bool 数组:默认值为 false
5) 使用数组的步骤1.声明数组并开辟空间 2给数组各个元素赋值 3使用数组
6) 数组的下标是从 0 开始的。
7) 数组下标必须在指定范围内使用,否则报 panic: 数组越界,比如
var arr [5]int 则有效下标为0-4
8) Go 的数组属值类型,在默认情况下是值传递,因此会进行值拷贝。数组间不会相互影响
9) 如想在其它函数中,去修改原来的数组,可以使用引用传递(指针方式)
10) 长度是数组类型的一部分,在传递函数参数时需要考虑数组的长度
// 这种写法是错误的,因为没有指定数组长度
func test(arr []int) {
}
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 随机生成 10 个数,并反转
var arr [10]int
rand.Seed(time.Now().Unix())
for i := 0; i < len(arr); i++ {
arr[i] = rand.Intn(100)
}
fmt.Println("before ", arr)
tmp := 0
for i := 0;i < len(arr) / 2; i++ {
tmp = arr[len(arr) - 1 - i]
arr[len(arr) - 1 - i] = arr[i]
arr[i] = tmp
}
fmt.Println("after ", arr)
}
var 变量名 []类型
比如: var a [] int
// 演示切片的基本使用
var intarr [5]int = [...]int{1, 22, 33, 66, 99}
// 声明/定义一个切片
// slice := intArr[1:3]
// 1. slice 就是切片名
// 2. intArr[1:3]表示slice 引用到intArr这个数组
// 3. 引用intArr数组的起始下标为1 ,最后的下标为3(但是不包含3)
slice := intArr[1:3]
fmt.Println( "intArr=" , intArr)
fmt.Println("slice的元素是=", slice) // 22, 33
fmt.Println("slice 的元素个数=", len(slice)) // 2
fmt.Println("slice 的容量=”, cap(slice)) // 切片的容量是可以动态变化
内存图
package main
import "fmt"
func main() {
intArr := [...]int {0, 1, 2, 3, 4, 5}
slice := intArr[1:3]
fmt.Printf("type %T, slice = %vn", slice, slice)
fmt.Println("slice 元素个数是 ", len(slice), ", 容量是 ", cap(slice))
slice[0] = 11
fmt.Println("intArr =", intArr)
}
切片的使用
intArr := [...]int {0, 1, 2, 3, 4, 5}
slice := intArr[1:3]
基本语法: var 切片名 []type = make([], len, [cap])
参数说明: type 就是数据类型, len 大小,cap 指定切片容量,可选
package main
import "fmt"
func main() {
var slice []int = make([]int, 5)
for i := 0; i < len(slice); i++ {
slice[i] = i
}
fmt.Println("slice = ", slice)
}
package main
import "fmt"
func main() {
var slice []int = []int {0, 1, 2, 3, 4}
fmt.Println("slice = ", slice)
}
方式1和方式2的区别(面试)
方式一是直接引用数组,这个数组是事先存在的,程序员是可见的。
方式二是通过 make 来创建切片,make 也会创建一个数组,是由切片在底层进行维护【此数组没有名称】,程序员是看不见的。
切片的遍历方式
package main
import "fmt"
func main() {
var slice []int = []int {0, 1, 2, 3, 4}
for i := 0; i < len(slice); i++ {
fmt.Printf("slice[%v] = %vn", i, slice[i])
}
for key,value := range slice {
fmt.Println("key = ", key, ", value = ", value)
}
}
切片注意事项和细节说明
说明:从 arr 数组 下标为startIndex,取到下标为endIndex的元素(不含
arrendIndex])。
动态增长
切片 append 操作的底层原理分析:
package main
import "fmt"
func main() {
var slice []int = []int {0, 1, 2, 3, 4}
slice1 := append(slice, 5, 6, 7, 8)
slice = append(slice1, slice...)
fmt.Println("slice1", slice1)
fmt.Println("slice", slice)
}
也可以对没有 make 的切片直接 append
func test() {
var t []int
t = append(t,1)
t = append(t,1)
t = append(t,1)
t = append(t,1)
fmt.Println(t)
}
切片的拷贝
(1) copy(para1, para2)参数的数据类型是切片
(2) 按照上面的代码来看,slice4 和 slice5 的数据空间是独立,相互不影响,也就是说 slice4[0]= 999 slice5[0] 仍然是1
package main
import "fmt"
func main() {
var slice []int = []int {0, 1, 2, 3, 4}
slice2 := make([]int, 10)
copy(slice2, slice)
slice2[0] = 100
fmt.Println("slice = ", slice)
fmt.Println("slice2 = ", slice2)
}
注意:切片和数组的定义
var slice []int = []int {0, 1, 2, 3, 4} // 切片,[]不需要声明长度
var slice [5]int = [5]int {0, 1, 2, 3, 4} // 数组,[5]需要声明长度
string 和 slice
package main
import "fmt"
func main() {
str := "hello@guigu"
slice := str[6:]
fmt.Println("slice", slice)
// []byte(str)可以处理中文和数字,但是中文就会出现乱码
// bt := []byte(str)
bt := []rune(str) // 这个是按字符来处理的,而不是按一个一个字节处理
bt[0] = 'H'
str = string(bt)
fmt.Println("str", str)
}
细节,我们转成[]byte后,可以处理英文和数字,但是不能处理中文
原因是[]byte 字节来处理,而一个汉字,是 3 个字节,因此就会出现乱码
解决方法是将 string 转成 []rune 即可,因为 []rune 是按字符处理,兼容汉字
package main
import "fmt"
// 把斐波那契数列放入切片
func fbn(n int) ([]uint64) {
slice := make([]uint64, n)
slice[0] = 1
slice[1] = 1
for i := 2; i < n; i++ {
slice[i] = slice[i - 1] + slice[i - 2]
}
return slice
}
func main() {
fbn := fbn(10)
fmt.Println("fbn = ", fbn)
}
二维数组
使用方式:先声明/定义再赋值
package main
import "fmt"
func main() {
var arr [4][6]int
arr[1][2] = 1
arr[2][1] = 2
arr[2][3] = 3
for i := 0; i < 4; i++ {
for j := 0; j < 6; j++ {
fmt.Print(arr[i][j], " ")
}
fmt.Println()
}
}
初始化
二维数组的遍历
package main
import (
"fmt"
)
func main() {
var arr = [4][6]int {{1, 2, 3}, {4, 5, 6}}
for i := 0; i < len(arr); i++ {
for j := 0; j < len(arr[i]); j++ {
fmt.Printf("arr[%v][%v] = %v, ", i, j, arr[i][j])
}
fmt.Println()
}
for k, v := range arr {
for kk, vv := range v {
fmt.Printf("arr[%v][%v] = %v,", k, kk, vv)
}
fmt.Println()
}
}
map 是 key-value 数据结构,又称为字段或者关联数组。类似其它编程语言的集合,
在编程中是经常使用到。
map 的声明
基本语法
var map变量名 map[keytype]valuetype
golang 中的 map 的 key 可以是很多种类型,比如 bool,数字,string, 指针,channel 还可以是只包含前面几个类型的接口,结构体,数组,通常为int、string
注意 slice, map 还有function 不可以,因为这几个没法用 == 来判断
基本语法
var map变量名 map[keytype]valuetype
valuetype 的类型和 key 基本一样,这里我就不再赘述了
通常为:数字(整数,浮点数),string,map struct
map声明的举例:
var a map[string]string
var a map[string]int
var a map[int]string
var a map[string]map[string]string
注意:声明是不会分配内存的,初始化需要 make,分配内存后才能赋值和使用。
三种声明
package main
import "fmt"
func main() {
// 1
var a map[string]string
a = make(map[string]string)
a["no1"] = "宋江"
a["no2"] = "宋江"
a["no3"] = "宋江"
a["no4"] = "宋江"
fmt.Println(a)
// 2
cities := make(map[string]string)
cities["no1"] = "北京"
cities["no2"] = "北京"
cities["no3"] = "北京"
cities["no4"] = "北京"
fmt.Println(cities)
// 3
heroes := map[string]string {
"no1" : "heroes1",
"no2" : "heroes1",
"no3" : "heroes1",
"no4" : "heroes1",
}
fmt.Println(heroes)
}
复杂类型的
students := make(map[string]map[string]string)
students["01"] = make(map[string]string)
students["01"]["sex"] = "male"
students["01"]["age"] = "15"
students["01"]["address"] = "beijing"
students["02"] = make(map[string]string)
students["02"]["sex"] = "male"
students["02"]["age"] = "15"
students["02"]["address"] = "beijing"
map 的增删改查操作
map["'key"] = value // 如果 key 还没有,就是增加,如果 key 存在就是修改。
delete(map, “key”) ,delete 是一个内置函数,如果 key 存在,就删除该 key-value,如果 key 不存在,不操作,但是也不会报错
➢细节说明
delete(students, "01")
fmt.Println(students)
students = make(map[string]map[string]string)
fmt.Println(students)
city, ok := cities["no3"]
if ok {
fmt.Println("yes, city is ", city)
} else {
fmt.Println("no")
}
案列演示相对复杂的 map 遍历:该 map 的 value 又是一个 map
map的遍历使用for-range的结构遍历
package main
import "fmt"
func main() {
var a map[string]string
a = make(map[string]string)
a["no1"] = "宋江"
a["no2"] = "宋江"
a["no3"] = "宋江"
a["no4"] = "宋江"
for key, value := range a {
fmt.Printf("key = %v, value = %vn", key, value)
}
students := make(map[string]map[string]string)
students["01"] = make(map[string]string)
students["01"]["sex"] = "male"
students["01"]["age"] = "15"
students["01"]["address"] = "beijing"
students["02"] = make(map[string]string)
students["02"]["sex"] = "male"
students["02"]["age"] = "15"
students["02"]["address"] = "beijing"
for key, value := range students {
fmt.Println("key = ", key)
for k, v := range value {
fmt.Printf("k = %v, v = %vn", k, v)
}
}
}
fmt.Println("students len is ", len(students))
map 切片
基本介绍
切片的数据类型如果是 map,则我们称为 slice of map, map 切片,这样使用则
map 个数就可以动态变化了。
package main
import "fmt"
func main() {
var monsters []map[string]string
monsters = make([]map[string]string, 2)
if monsters[0] == nil {
monsters[0] = make(map[string]string, 2)
monsters[0]["name"] = "牛魔王"
monsters[0]["age"] = "500"
}
if monsters[1] == nil {
monsters[1] = make(map[string]string, 2)
monsters[1]["name"] = "玉兔精"
monsters[1]["age"] = "400"
}
newMonster := map[string]string {
"name" : "火云邪神",
"age" : "100",
}
monsters = append(monsters, newMonster)
fmt.Println(monsters)
}
map排序
package main
import (
"fmt"
"sort"
)
func main() {
//如果按照map的key的顺序进行排序输出
//1. 先将map的key 放入到切片中
//2. 对切片排序
//3. 遍历切片,然后按照key来输出map的值
a := make(map[int]int)
a[0] = 0
a[1] = 1
a[2] = 2
a[3] = 3
a[4] = 4
var slice []int
for index, _ := range a {
slice = append(slice, index)
}
sort.Ints(slice)
fmt.Println(slice)
for _, v := range slice {
fmt.Printf("a[%v] = %vn", v, a[v])
}
}
map 使用细节
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!