Go 语言学习笔记 -第4章
[toc]
复合数据类型
数组
Golang中操作数组或者序列化数据需要用到slice,程序中写作“[]"
slice 指向数组的值,并且同时包含了长度信息
package main
import "fmt"
func main() {
// list := []int{1, 2, 3, 4}
list := [...]int{1, 2, 3, 4}
fmt.Println(list)
fmt.Printf("Type %T\n", list)
for i := 0; i < len(list); i++ {
fmt.Printf("list[%d]=%d\n", i, list[i])
}
//重新切片s[low:high], low->(high-1)
fmt.Println(list[1:1]) //[]
fmt.Println(list[0:3]) //[1 2 3]
fmt.Println(list[:2]) //[1 2]
fmt.Println(list[1:]) //[2 3 4]
fmt.Println(list[:0]) //[]
}
切片slice
package main
import "fmt"
func main() {
//使用make进行声明切片
list := make([]int, 5)
fmt.Println("list=", list) //list= [0 0 0 0 0]
fmt.Printf("len=%d,cap=%d", len(list), cap(list)) //len=5,cap=5
}
切片长度和容量,长度为5,容量为5
默认情况下长度和容量是一样的
怎么理解长度和容量?
切片的长度就是它所包含的元素个数。
切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。
再看一个例子:
package main
import "fmt"
func main() {
aSlice := []int{1, 2, 3, 4, 5}
fmt.Printf("before aSlice length=%d,cap=%d,self=%v\n", len(aSlice), cap(aSlice), aSlice)
//before aSlice length=5,cap=5,self=[1 2 3 4 5]
aSlice = append(aSlice, 6)
fmt.Printf("after aSlice length=%d,cap=%d,self=%v\n", len(aSlice), cap(aSlice), aSlice)
//after aSlice length=6,cap=10,self=[1 2 3 4 5 6]
//这里如何理解?加入一个元素,但是容量增加了一倍?并没有变成6?
bSlice := make([]int, 5, 10)
bSlice[0] = 1
bSlice[1] = 2
bSlice[2] = 3
bSlice[3] = 5
bSlice[4] = 6
fmt.Printf("before bSlice length=%d,cap=%d,self=%v\n", len(bSlice), cap(bSlice), bSlice)
//before bSlice length=5,cap=10,self=[1 2 3 5 6]
bSlice = append(bSlice, 6)
fmt.Printf("after bSlice length=%d,cap=%d,self=%v\n", len(bSlice), cap(bSlice), bSlice)
//after bSlice length=6,cap=10,self=[1 2 3 5 6 6]
// list := make([]int, 3, 5)
// fmt.Println(len(list), cap(list))
// list[0] = 1
// list[1] = 2
// list[2] = 3
// // list[3] = 4
// fmt.Println(len(list), cap(list))
// fmt.Println("list=", list)
}
如果我们最开始 slice 的容量是 10,长度是 5 ,那么再加一个元素是不会改变切片的容量的。
也就是说,当我们往 slice中增加元素超过原来的容量时,slice 会自增容量,
当现有长度 < 1024 时 cap 增长是翻倍的,当超过 1024,cap 的增长是 1.25 倍增长
可以查看slice.go源码
下面几个链接地址可以看看:
map散列
1.map 的作用类似哈希表或者python里面的字典
基本语法:
var map 变量名 map[keytype] valuetype
valuetype的类型和key基本一样:
通常为: 数字、string、map、struct
注意:
声明式不会分配内存的,初始化需要make,分配内存后才能赋值和使用
例子:
package main
import "fmt"
func main() {
//map声明
var a map[string]string
a = make(map[string]string)
//上面两行也可以写成一行 a := make(map[string]string)
//在使用map前,需要先make, make的作用是给map分配数据空间
//key不能重复,如果重复了以最后一个为准
//值是可以重复的
//key-value是无序的, 也就是print没有顺序
//这里如果值写的是整数类型而不是字符串类型,就会报错-----强判断型
a["no1"] = "AA"
a["no2"] = "BB"
a["no1"] = "CC"
a["no3"] = "DD"
fmt.Println(a)
}
2.map三种方式
package main
import "fmt"
func main() {
//第一种方式
// var a map[string]string
// a = make(map[string]string, 10)
//第二种方式
// a := make(map[string]string)
// a["no1"] = "AA"
// a["no2"] = "BB"
// a["no1"] = "CC"
// a["no3"] = "DD"
//第三种方式
a := map[string]string{
"no1": "AA",
"no2": "BB",
}
fmt.Println("a=", a)
}
3.map的使用
package main
import "fmt"
func main() {
a := make(map[string]string)
a["no1"] = "AA"
a["no2"] = "BB"
a["no1"] = "CC"
a["no3"] = "DD"
//删除
// delete(a, "no1")
//删除不存在的key,删除不会操作,也不会报错
// delete(a, "no4")
//一次性删除所有key
// a = make(map[string]string)
//查询key
val, ok := a["no6"]
if ok {
fmt.Println("no1=", val)
} else {
fmt.Println("没有key")
}
}
4.map遍历
package main
import "fmt"
func main() {
a := make(map[string]string)
a["no1"] = "AA"
a["no2"] = "BB"
a["no1"] = "CC"
a["no3"] = "DD"
//遍历map
// for k, v := range a {
// fmt.Printf("k=%v, v=%v\n", k, v)
// }
//长度
fmt.Println("length:", len(a))
}
5.map切片
package main
import "fmt"
func main() {
a := make([]map[string]string, 2)
if a[0] == nil {
a[0] = make(map[string]string, 2)
a[0]["no1"] = "AA"
a[0]["no2"] = "BB"
}
if a[1] == nil {
a[1] = make(map[string]string, 2)
a[1]["no1"] = "CC"
a[1]["no2"] = "DD"
}
// if a[2] == nil {
// a[2] = make(map[string]string, 2)
// a[2]["no1"] = "EE"
// a[2]["no2"] = "FF"
// }
//动态增加
newa := map[string]string{
"no1": "111",
"no2": "22",
}
a = append(a, newa)
fmt.Println("a:", a)
}
结构体
Golang没有class, 用结构体来实现class特征
去掉了传统OOP的继承、方法重载、构造函数、析构函数、隐藏的this指针等
具体继承、封装、多态,只是实现方式跟其他OOP语言不一样
1.结构体例子
package main
import "fmt"
//结构体
type Cat struct {
Name string
Age int
Color string
}
func main() {
var cat1 Cat
//访问结构体变量,直接用.符号连接
//结构体可以給部分成员赋值
cat1.Name = "小白"
cat1.Age = 3
cat1.Color = "白色"
fmt.Println("cat1=", cat1)
}
2.结构体与slice map
package main
import "fmt"
//结构体
type Cat struct {
Name string
Age int
Color string
ptr *int
slice []int
map1 map[string]string
}
func main() {
var cat1 Cat
cat1.Name = "小白"
cat1.Age = 3
cat1.Color = "白色"
//使用slice要先make
cat1.slice = make([]int, 10)
cat1.slice[0] = 100
//使用map要先make
cat1.map1 = make(map[string]string)
cat1.map1["key1"] = "tom"
fmt.Println("cat1=", cat1)
}
3.结构体赋值
package main
import "fmt"
//结构体
type Monster struct {
Name string
Age int
}
func main() {
var monster1 Monster
monster1.Name = "牛魔王"
monster1.Age = 500
monster2 := monster1 //默认是值拷贝
monster2.Name = "狐狸精"
fmt.Printf("monster1=%v, monster2=%v", monster1, monster2)
//monster1={牛魔王 500}, monster2={狐狸精 500}
}
package main
import "fmt"
//结构体
type Monster struct {
Name string
Age int
}
func main() {
//方法1
// var monster1 Monster
// monster1 := Monster{}
// monster1.Name = "牛魔王"
// monster1.Age = 500
//方法2
// monster1 := Monster{"牛魔王", 500}
//方法3
var p3 *Monster = new(Monster)
(*p3).Name = "牛魔王"
(*p3).Age = 500
//(*p3).Name也可以写成p3.Name = "xxx"
p3.Name = "狐狸精"
p3.Age = 100
//方法4, 通过指针进行获取
var monster *Monster = &Monster{}
(*monster).Name = "玉兔精"
// monster.Name = "XX"
fmt.Printf("monster1=%v", monster)
}