map和结构体
一、map 引用类型
map是引用类型
1、定义和初始化
- make定义
// 方式1 var mapT1 map[string]string mapT1 = make(map[string]string, 10) // 方式2 var mapT3 = make(map[string]string) // 方式3 mapT4 := make(map[string]string) // 赋值 mapT4["number1"] = "11111" mapT4["number2"] = "22222" // 输出 => map[number1:11111 number2:22222]
- 普通定义
var mapT2 = map[int]int{} mapT2 := map[int]int{} // 赋值 mapT2 := map[int]int{ 1:1, 2:2, } // 输出 => map[1:1 2:2]
2、map的嵌套结构
- map[int]map[string]string
type mapSS map[int]map[string]string func Anli() { // 方式1 students := make(map[int]map[string]string) students[1] = map[string]string{ "name": "张三", "sex": "男", } students[2] = map[string]string{ "name": "张四", "sex": "男", } students[3] = map[string]string{ "name": "张五", "sex": "女", } // fmt.Println(students) // 输出 =》map[1:map[name:张三 sex:男] 2:map[name:张四 sex:男] 3:map[name:张五 sex:女]] // 方式2 stus := mapSS{ 1:{ "name": "王武", "age": "20", }, 2:{ "name": "王六", "age": "24", }, 3:{ "name": "王七", "age": "30", }, } fmt.Println(stus) a, b := stus[1]["name"] fmt.Println(a, reflect.TypeOf(b)) // 输出 =》 map[1:map[age:20 name:王武] 2:map[age:24 name:王六] 3:map[age:30 name:王七]] }
- 带入实例理解下
(1)商品列表:map[int]map[string]string
:(一对一)
(2)商品评价:[ 商品id:{名称:‘’, 描述:‘’}, 商品id:{名称:‘’, 描述:‘’}, ........ ]
map[int][]map[string][string]
:(一对多)[ 商品id:[ {用户id:1, 评价:‘’}, {用户id:2, 评价:‘’}, ....... ], 商品id:[ {用户id:1, 评价:‘’}, {用户id:2, 评价:‘’}, ....... ], ........ ]
2、map切片
make([]map[int]int, 2, 4)
func SliceMap() {
a := make([]map[int]int, 2, 4)
// 赋值方式1
a[0] = make(map[int]int)
a[0][1] = 1
// 赋值方式2
a[1] = map[int]int{0:0, 1:1}
// 切片追加
a = append(a, map[int]int{2:2})
}
3、map遍历和排序
- 遍历
mapm := map[int]string{ 11: "测试11", 22: "测试22", } for key, item := range mapm { fmt.Println(key, item) }
- 排序
golang中map是无序的,没有对map排序的方法。实现思路:先将key放到切片中,对切片排序,遍历切片取出value
func SortMap() {
mapm := map[int]int{
10: 1,
4: 2,
3: 3,
13: 3,
33: 3,
}
// 存放map的key的切片
sliceMap := []int{}
// map遍历
for key, _ := range mapm {
// append key到切片
sliceMap = append(sliceMap, key)
}
// 对切片排序
sort.Ints(sliceMap)
// 按照切片顺序遍历
for _, item := range sliceMap {
fmt.Print(mapm[item], "\t")
}
}
4、map和结构体
// 定义结构体
type stu struct {
id int
name string
age int
}
func StructMap() {
// map的value指定为结构体类型
a := map[int]stu{}
stu1 := stu{
id: 1,
name: "张三",
age: 20,
}
stu2 := stu{
id: 2,
name: "张三",
age: 21,
}
a[0] = stu1
a[1] = stu2
fmt.Println(a)
fmt.Println(a[0].name)
a1 := []stu{}
a1 = append(a1, stu1)
fmt.Println(a1)
}
5、map增删改查
- 增和改
如果key存在就是跟新,如果不存在就是插入 - 删
delete(map[type]type, key)
- 查
方式1:
方式2:// 参数一:key=1 对应的值 // 参数二:是否存在, 有返回true, 没有返回false stu, isOrNo := stus[1]
引用类型没有初始化,引用为nil
(空)。值类型,初始化不为nil
stu := stus[1] if stu == nil { // 不存在 } else { // 存在 }
6、map判断是否存在key
// 存在 ok:true
// 不存在反之
_, ok := map1[1]
二、结构体 值类型
可以理解为一个自定义的数据类型,就是一个结构体(等同于自定义int、string、float等数据类型);创建、引用对象和值类型的基本数据类型一致。
1、定义
type Cat struct {
Name string
Age int
Color string
Teacher *string
}
func DY() {
// 方式1
var cat Cat
fmt.Println(cat) // 输出 =》{ 0 <nil>}
// 方式2
cat2 := Cat{}
fmt.Println(cat2) // 输出 =》{ 0 <nil>}
// 方式3
// new一个指针,引用类型
cat3 := new(Cat) //等价 (var cat3 *Cat = new(Cat))
(*cat3).Name = "aaa"
cat3.Name = "bbb" // 两种写法都可以,底层转化为=》(*cat3).Name = "bbb"
fmt.Println(*cat3) // 输出 =》{bbb 0 <nil>}
// 方式4
cat4 := &Cat{}
(*cat4).Name = "111"
fmt.Println(*cat4) // =》{111 0 <nil>}
}
2、结构体切片
str := ""
cat1 := Cat{"小花", 10, "红色", &str}
cat2 := Cat{"小白", 1, "白色", &str}
sliceCat := []Cat{cat1, cat2}
3、结构体指针
func setCat(cat *Cat) {
cat.Name = "小小"
fmt.Println(cat.Name)
}
func main(){
cat := new(Cat)
(*cat).Name = "大大"
// 此处参数是指针,所以是引用传递,会修改当前对象
setCat(cat)
fmt.Println(cat)
// 输出 =》
// { "小小" }
// { "小小" }
}
4、结构体序列化
type Cat struct {
// `json:"name"` 指定序列化后的 Name =》name
Name string `json:"name"`
Age int
Color string
}
func JsonM() {
str := ""
cat1 := Cat{"小花", 10, "红色"}
// json序列化
catt, err := json.Marshal(cat1)
// 转化为strings输出,否则为字节码
fmt.Println(string(catt), err)
// 输出 =》{"name":"小花","Age":10,"Color":"红色"} <nil>
}
func main(){
other.JsonM()
}
5、结构体内存结构
结构体每个值的内存地址是连续的,但是指针类型存储的值的地址不是连续