Go语言基础语法和注意事项总结(下)| 青训营

127 阅读8分钟

八.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)接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法。接口体现了程序设计的多态和高内聚低耦合的思想。

  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 中的核心概念之一,它为多态性提供了强大的支持,允许不同的类型以一致的方式被使用。接口使得代码更加灵活和可扩展,同时也促进了模块化和低耦合的设计。