八.map
1.介绍
基本语法: var map 变量名 map [key数据类型]value数据类型
其中key通常为int、string类型,也可以是bool、指针、channel等类型。但是不可以为slice、map、function类型,因为这个几个没法用==来判断。
value的类型和key基本一样
注意:声明是不会分配内存的,初始化需要make分配内存后才可赋值和使用
2.map的增删改查
(1)增加和更新
map[key]=value//如果key还没有,就是增加,如果key已存在就是修改
(2)删除
使用delete(map,key),delete是一个内置函数,如果key存在就删除,不存在就不进行任何操作
注意:如果要删除map的所有key,只能通过遍历key来逐个删除,或者map=make(...),make一个新的让原来的成为垃圾,被gc回收
(3)查找
value,bool = map[key]
3.map使用细节
(1)map为引用类型,在一个函数接受map,修改后会直接修改原来的map
(2)map能动态增长,自动扩容
(3)map的value经常使用struct类型,更适合管理复杂的数据
思考:
Map 在 Go 语言中是非常常用的数据结构,用于存储和快速检索键值对。它的动态增长和自动扩容特性使其在各种场景中都很有用。尤其在需要构建映射关系的情况下,例如构建字典、缓存等。
九.结构体
1.结构体的声明
type 结构体名称 struct {
字段名称(属性) 数据类型
...
}
2.结构体使用细节
(1)结构体的所有字段在内存中是连续的
(2)结构体和其他类型转换时需要有完全相同的字段
(3)在创建结构体变量时,把字段名和字段值写在一起,这种方式不依赖字段的定义顺序
思考:
结构体是构建复杂数据类型的基础,它使得程序可以更有结构地组织数据。通过结构体的嵌套,可以实现数据的层次化管理,从而增强代码的可读性和可维护性。
十.方法
1.方法的声明
//给Person类型绑定一个方法
func (变量 数据类型) 方法名(参数列表) 返回值列表 {
...
}
func main(){
var p Person
p.test()//调用方法
}
2.方法使用细节
(1)结构体类型是值类型,在方法调用中是值拷贝传递方式
(2)Golang中的方法是作用在指定的数据类型上的(即和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是struct
(3) 方法的调用和传参机制原理和函数基本一样,不一样的地方是,变量调用方法时会将调用方法的变量,当作实参也传递给方法,如果该变量是值类型则进行值拷贝,如果变量是引用类型,则进行地址拷贝
3.方法和函数区别
(1)调用方式不同
函数的调用方式: 函数名(实参列表)
方法的调用方式: 变量.方法名(实参列表)
(2)对于函数,接受者为值类型时,不能将指针类型的数据直接传递,反之亦然
(3)对于方法,接受者为值类型时,可以直接用指针类型的变量调用方法,反之亦然
思考:
方法是面向对象编程中的核心概念,它允许我们将操作与数据紧密关联,提高了代码的封装性和可维护性。通过方法,我们可以实现类型的行为抽象,更好地模拟现实世界中的概念。
十一.封装
1.介绍
封装就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作,才能对字段进行操作
2.好处
(1)隐藏实现细节 (2)可以对数据进行验证,保证安全合理
3.封装的实现步骤
(1)将结构体、字段的首字母小写,不可导出
(2)给结构体所在包提供一个工厂模式的函数,首字母大写。类似一个构造函数
(3)提供一个Set方法(类似public),用于对属性判断并赋值
func (var 结构体类型名) SetXxx(参数列表) (返回值列表){
//加入数据验证的业务逻辑
var.字段=参数
}
4.提供一个Get方法(类似public),用于获取属性的值
func (var 结构体类型名) GetXxx(){
return var.字段
}
思考:
封装是面向对象编程中的重要原则,它可以有效控制数据的访问权限,减少了错误的发生和影响范围。通过封装,我们可以隐藏实现细节,提供更高层次的接口,提升代码的可靠性。
十二.继承
1.介绍
继承可以解决代码复用。
当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体(比如刚才的Student),在该结构体中定义这些相同的属性和方法。
其它的结构体不需要重新定义这些属性和方法,只需嵌套一个Student匿名结构体即|可。
也就是说:在Golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。
2.继承的深入讨论
(1)结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用。
(2)当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分
var b B
b.name = "jerry" //这时就近原则会访问B结构体的name字段
b.A.name //明确指定访问A匿名结构体的字段name
方法同理
(3) 结构体嵌入两个(或多个)匿名装构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。
(4)如果一个struct嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字
(5)嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值
思考:
虽然 Golang 并没有经典的继承机制,但通过结构体嵌套可以实现类似的效果。这种组合的方式在某些情况下更加灵活,避免了继承链的复杂性,同时也能实现代码的复用。
十三.接口
1.介绍
interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。到某个自定义类型(比如结构体Phone)要使用的时候,在根据具体情况把这些方法写出来。
1)接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法。接口体现了程序设计的多态和高内聚低耦合的思想。
- Golang中的接口,不需要显式的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,Golang中没有implement这样的关键字
2.基本语法
type接口名 interface{
method1(参数列表}返回值列表
method2(参数列表)返回值列表
}
3.注意事项和细节
(1)接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量
(2)接口中所有的方法都没有方法体
(3)在Go中,一个自定义类型需要将某个接口的所有方法都实现,则这个自定义类型实现了该接口
(4)一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型。
(5)只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。
(6)一个自定义类型可以实现多个接口
(7)Go接口中不能有任何变量
(8)一个接口(比如A接口)可以继承多个别的接口(比如B,c接口),这时如果要实现A接口,也必须将B,c接口的方法也全部实现。
(9)interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用那么会输出nil
(10)空接口inigerface没有任何方法,所以所有类型都实现了空接口
思考:
接口是 Golang 中的核心概念之一,它为多态性提供了强大的支持,允许不同的类型以一致的方式被使用。接口使得代码更加灵活和可扩展,同时也促进了模块化和低耦合的设计。