字典与结构体
# 1.map(字典,映射)
- 只要是可以做==、!=判断的数据类型都可以作为 key(数值类型、字符串、数组、指针、结构体、接口)。
- map 的 key 的数据类型不能是:slice、map、function。
- map 和切片一样容量都不是固定的, 当容量不足时底层会自动扩容。
- 切片是用来存储一组相同类型的数据的, map 也是用来存储一组相同类型的数据的。
- 在切片中我们可以通过索引获取对应的元素, 在 map 中我们可以通过 key 获取对应的元素。
- 切片的索引是系统自动生成的,从 0 开始递增. map 中的 key 需要我们自己指定
- 创建 map 的三种方式
package main
import "fmt"
func main() {
//map格式:var dic map[key数据类型]value数据类型
//方式一: 通过Go提供的语法糖快速创建
dict := map[string]string{"name": "lnj", "age": "1", "gender": "male"}
fmt.Println(dict) // map[name:lnj age:33 gender:male]
//方式二:通过make函数创建make(类型, 容量)
var dict1 = make(map[string]string, 3)
dict1["name"] = "lnj"
dict1["age"] = "2"
dict1["gender"] = "male"
fmt.Println(dict1) // map[age:33 gender:male name:lnj]
//方式三:通过make函数创建make(类型)
var dict2 = make(map[string]string)
dict2["name"] = "lnj"
dict2["age"] = "3"
dict2["gender"] = "male"
fmt.Println(dict2) // map[age:33 gender:male name:lnj]
// 注意:map声明后不能直接使用, 只有通过make或语法糖创建之后才会开辟空间,才能使用
var dict3 map[string]string
dict3["name"] = "lnj" // 编译报错
dict3["age"] = "33"
dict3["gender"] = "male"
fmt.Println(dict3)
- map 的增删改查
package main
import "fmt"
func main() {
//增加: 当map中没有指定的key时就会自动增加
var dict = make(map[string]string)
fmt.Println("增加前:", dict) // map[]
dict["name"] = "lnj"
fmt.Println("增加后:", dict) // map[name:lnj]
//修改: 当map中有指定的key时就会自动修改
var dict1 = map[string]string{"name": "lnj"}
fmt.Println("修改前:", dict1) // map[name:lnj]
dict1["name"] = "zs"
fmt.Println("修改后:", dict1) // map[name:zs]
//删除: 可以通过Go语言内置delete函数删除指定元素
var dict2 = map[string]string{"name": "lnj", "age": "33", "gender": "male"}
fmt.Println("删除前:", dict2) // map[name:lnj age:33 gender:male]
// 第一个参数: 被操作的字典
// 第二个参数: 需要删除元素对应的key
delete(dict2, "name")
fmt.Println("删除后:", dict2) // map[age:33 gender:male]
//查询: 通过ok-idiom模式判断指定键值对是否存储
var dict3 = map[string]string{"name": "lnj", "age": "33", "gender": "male"}
//value, ok := dict["age"]
//if(ok){
// fmt.Println("有age这个key,值为", value)
//}else{
// fmt.Println("没有age这个key,值为", value)
//}
if value, ok := dict3["age"]; ok {
fmt.Println("有age这个key,值为", value)
}
//遍历
//注意: map和数组以及切片不同,map中存储的数据是无序的, 所以多次打印输出的顺序可能不同
var dict4 = map[string]string{"name": "lnj", "age": "33", "gender": "male"}
for key, value := range dict4 {
fmt.Println(key, value)
}
}
# 2.结构体
package main
import "fmt"
func main() { //创建结构体变量的两种方式
//第一种方式
type Student struct {
name string
age int
}
var stu1 = Student{"lnj", 33} // 完全初始化
fmt.Println(stu1)
// 部分初始化必须通过 属性名称: 方式指定要初始化的属性
var stu2 = Student{name: "lnj"} // 部分初始化
fmt.Println(stu2)
//第二种方式
// 注意: 这里不用写type和结构体类型名称
var stu = struct {
name string
age int
}{
name: "lnj",
age: 33,
}
fmt.Println(stu)
}
结构体变量 以及 指针的定义方法。
1.直接定义结构体变量
type Person struct {
Name string
Age int
Gender string
}
func main() {
var p Person
p.Name = "Bob"
p.Age = 20
p.Gender = "Male"
fmt.Println(p)
}
在上面的示例中,我们直接通过 var 定义了一个 Person 类型的变量 p,然后使用点操作符来设置其字段的值。
2.使用字面量定义结构体变量 在 Go 语言中,可以使用结构体字面量来定义结构体变量:
func main() {
p := Person{Name: "Bob", Age: 20, Gender: "Male"}
fmt.Println(p)
}
使用结构体字面量的好处是可以直接在定义变量时就设置其字段的值,更加简洁易懂。
3.定义结构体指针变量 如果我们需要在函数之间传递结构体变量或在函数内部修改结构体字段的值,一种常见的方式是定义结构体指针变量:
func main() {
var p *Person
p = &Person{Name: "Bob", Age: 20, Gender: "Male"}
fmt.Println(p)
}
在上面的示例中,我们使用&符号获取结构体字面量的内存地址赋值给指针变量 p,从而定义了一个结构体指针变量。此后,我们可以使用指针操作符*来访问和修改其字段的值。
4.使用 new 函数动态分配结构体 Go 语言还提供了一个 new 函数,用于在堆上动态分配一个新的结构体变量,并返回一个指向其内存地址的指针:
func main() {
p := new(Person)
p.Name = "Bob"
p.Age = 20
p.Gender = "Male"
fmt.Println(p)
}
在上面的示例中,我们使用 new 函数来动态分配一个 Person 类型的变量,并通过点操作符来设置其字段的值。需要注意的是,new 函数返回的是一个指向已分配内存的指针,因此当使用它来定义一个新的变量时,需要使用指针类型来接收返回值。
package main
import "fmt"
type Teacher struct{}
func (tea Teacher) Action() string {
return "我是老师"
}
func main() {
//2.
t := Teacher{}
fmt.Println(t.Action())
//3.
var p *Teacher = &Teacher{}
fmt.Println(p.Action())
//4.
s := new(Teacher)
fmt.Println(s.Action())
}