数组
原创大约 5 分钟
数组
package main
import "fmt"
func main() {
// 容器:数组、切片、map和list
// 数组
var arr1 [3]int
var arr2 [4]int
// 虽然长度不同,但arr1和arr2是两种不同的类型
fmt.Printf("arr1: %T\r\n", arr1)
fmt.Printf("arr2: %T\r\n", arr2)
arr1[1] = 12
fmt.Println(arr1)
// 数组的初始化
arr3 := [3]int{1, 2, 3}
fmt.Println(arr3)
// 只初始化最后一个元素
arr4 := [3]int{2: 9}
fmt.Println(arr4)
// 另一种初始化:动态数组
arr5 := [...]int{1, 2, 3}
for i := 0; i < len(arr5); i++ {
fmt.Println(arr5[i])
}
// 多维数组
var arr6 [3][3]int
arr6[0] = [3]int{1, 2, 3}
// 打印二维数组
for i := 0; i < len(arr6); i++ {
for j := 0; j < len(arr6[i]); j++ {
fmt.Printf("%d ", arr6[i][j])
}
fmt.Println()
}
// 用range打印二维数组
for _, v := range arr6 {
for _, v1 := range v {
fmt.Printf("%d ", v1)
}
fmt.Println()
}
}
切片
package main
import (
"fmt"
"strconv"
)
func printSlice(data []string) {
// 呈现出引用传递的效果
data[0] = "java"
// 往data里面追加内容,但又不是引用传递,不会改变外部的值
for i := 0; i < 10; i++ {
data = append(data, strconv.Itoa(i))
}
fmt.Println(data)
}
func main() {
// 切片是一种动态数组,它允许我们存储任意数量的元素,并且这些元素可以有不同的类型,但切片绝对不是数组
var name []int
name = append(name, 1, 2, 3, 4)
fmt.Println(name)
// 切片可以不用初始化
// 切片的初始化方式有3种
// 1. 从数组直接创建
var name2 = []int{1, 2, 3, 4}
// 左闭右开的区间:[)
// 0:从第几个元素开始,2:到第几个元素结束
// 开始元素为闭区间,结束元素为开区间
sliceInit := name2[0:2]
fmt.Println(sliceInit)
// 2. 使用[]int{...}方式创建
sliceInit = []int{20, 21, 22}
fmt.Println(sliceInit)
// 3. 使用make函数
// make函数创建一个切片
sliceInit = make([]int, 3)
sliceInit[1] = 22
fmt.Println(sliceInit)
var name3 []int
// 这里如果使用name3[0]初始化元素会报错
// name3[0] = 1
for i := 0; i < 5; i++ {
name3 = append(name3, i)
}
fmt.Println(name3)
// 访问切片的元素
// 访问单个元素
fmt.Println(name3[0])
// 访问多个元素:name3[start:end],start和end都是选填的
fmt.Println(name3[1:4])
fmt.Println(name3[1:])
fmt.Println(name3[:3])
fmt.Println(name3[:])
// 通过省略号添加多个元素到切片
name3 = append(name3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
fmt.Println(name3)
// 切片的长度和容量
fmt.Println(len(name3))
fmt.Println(cap(name3))
// 添加数据到切片
name3 = append(name3[:2], name3[3:]...)
var name4 = append(name3[:2], name3...)
fmt.Println(name3)
fmt.Println(name4)
// 切片元素的删除
var name5 = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
name5 = append(name5[:4], name5[5:]...)
fmt.Println(name5)
// 复制切片
var name6 = make([]int, 10)
// 使用源切片的内容,而内容的长度和目标切片的长度保持一致
copy(name5, name6)
fmt.Println(name5)
//var i int = 10
//var j = 20
//k := 30
//fmt.Println(i, j, k)
// go的slice在函数参数传递的时候是值传递还是引用传递?
// 值传递,但呈现出引用传递的效果
data := []string{"go", "grpc", "gin", "mysql"}
printSlice(data)
data = append(data, "test1", "test2", "test3", "test4", "test5")
fmt.Println(data)
fmt.Println()
fmt.Println("==============================")
fmt.Println()
test := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
sub1 := test[1:5]
sub2 := test[2:6]
// 改变sub2的值,也会改变sub1和test的值
fmt.Println("改变sub2的值,也会改变sub1和test的值")
sub2[0] = 100
fmt.Println(sub1)
fmt.Println(sub2)
fmt.Println(test)
fmt.Println()
// 改变sub1的值,不会改变sub2和test的值
fmt.Println("改变sub1的值,也会改变sub2和test的值")
sub1[2] = 200
fmt.Println(sub1)
fmt.Println(sub2)
fmt.Println(test)
fmt.Println()
// 通过append,就不会再让sub2和test受影响,因为扩容后会指向新的地址
fmt.Println("但通过append,就不会再让sub2和test受影响")
sub1 = append(sub1, 20, 21, 22, 23, 24, 25, 26)
fmt.Println(sub1)
fmt.Println(sub2)
fmt.Println(test)
fmt.Println()
fmt.Println("append之后再来试试")
sub1[3] = 300
fmt.Println(sub1)
fmt.Println(sub2)
fmt.Println(test)
fmt.Println()
fmt.Println()
fmt.Println("==============================")
fmt.Println()
fmt.Println("切片的容量的效果展示")
test = []int{}
for i := 0; i < 2000; i++ {
test = append(test, i)
// 当达到512开始之后,容量不再翻倍,而是线性增长
fmt.Printf("len = %d, cap = %d\r\n", len(test), cap(test))
}
}
map
package main
import "fmt"
func main() {
// map一定要记得初始化
// 第一种初始化方式
mymap1 := map[string]string{
"name": "mymap1",
"age": "18",
}
// 遍历map,遍历顺序与存储顺序无关,而且每次遍历不保证顺序一样
// 所以如果想保证,不能仅仅只使用map
for k, v := range mymap1 {
println(k, v)
}
// 删除元素
delete(mymap1, "name")
fmt.Println("=======================")
// 插入和覆盖元素
mymap1["name"] = "mymap11"
mymap1["age"] = "22"
mymap1["gender"] = "男"
for k, v := range mymap1 {
println(k, v)
}
fmt.Println("=======================")
// 第二种初始化方式,这种方式会报错,因为此时的mymap2是nil
//var mymap2 map[string]string
//mymap2["name"] = "mymap2"
//fmt.Println(mymap2)
fmt.Println("=======================")
// 第三种初始化方式
mymap4 := make(map[string]string, 10)
mymap4["name"] = "mymap4"
fmt.Println(mymap4)
fmt.Println("=======================")
// map的遍历
for k := range mymap1 {
println(k)
}
fmt.Println("=======================")
//判断map中是否存在元素的两种方式
fmt.Println(mymap1["name"])
if _, ok := mymap1["java"]; ok {
println(mymap1["java"])
} else {
println("key not exist")
}
// 删除一个不存在的元素
delete(mymap1, "java")
// map不是线程安全的
}
list
package main
import (
"container/list"
"fmt"
)
func main() {
// list就是数据结构中的链表
// 默认list大小为4
//var mylist = list.List{}
// 另一种初始化方式
mylist := list.New()
fmt.Println(mylist)
mylist.PushBack("hello")
mylist.PushBack("world")
mylist.PushBack("bear")
mylist.PushBack("test")
mylist.PushBack("test2")
// 这里打印的是元素地址
fmt.Println(mylist)
fmt.Println("=============")
// 打印元素值
var e = mylist.Front()
fmt.Println(e)
fmt.Println("=============")
for e := mylist.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
//fmt.Println("=============")
// 反向遍历
//for e := mylist.Back(); e != nil; e = e.Prev() {
// fmt.Println(e.Value)
//}
fmt.Println("=============")
// 在hello和world之间插入元素
e = mylist.Front().Next()
mylist.InsertBefore("new element", e)
for e := mylist.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
fmt.Println("=============")
// 在bear和test之间插入元素
e = mylist.Front()
for ; e != nil; e = e.Next() {
if e.Value.(string) == "bear" { // 在bear之后,或者在test之前
break
}
}
mylist.InsertAfter("element2", e)
for e := mylist.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
fmt.Println("=============")
// 删除list中的元素
e = mylist.Front()
for ; e != nil; e = e.Next() {
if e.Value.(string) == "element2" {
mylist.Remove(e)
break
}
}
for e := mylist.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
/*
四种集合类型总结
数组 var test = [5]int{1,2,3,4,5}
切片 var test = []int{1,2,3,4,5}
map var test = map[string]int{"a":1,"b":2,"c":3}
list var test = list.New()
*/
}
感谢支持
更多内容,请移步《超级个体》。