- 接口和类型(结构体)的关系
- 一类型可以实现多个接口
- 多个类型可以实现同一个接口 (多态)
1..一个类型可以实现多个接口: 有一个player接口可以播放音乐,有一个vido接口可以播放视频,一个Phome可以同时实现这俩接口,边听儿歌变看视频。 ****************************************************** package main import ( "fmt" ) type Music interface { audio() } type Video interface { TV() } type Phone struct { name string } func (p Phone) audio() { fmt.Printf("%v,正在听音乐...", p.name) } func (p Phone) TV() { fmt.Printf("%v,正在看视频...", p.name) } func main() { var music Music var tv Video phone := Phone{ name: "iqoo", } music = phone //实体类赋值接口 tv = phone music.audio() tv.TV() } ****************************************************** 2.多个类型可以实现同一个接口 (多态) package main import ( "fmt" ) type Music interface { audio() } type Phone struct { name string } func (p Phone) audio() { fmt.Printf("%v,正在听音乐...", p.name) } type Computer struct { name string } func (c Computer) audio() { fmt.Printf("%v,正在听音乐...", c.name) } func main() { var music Music phone := Phone{ name: "iqoo", } music = phone //实体类赋值接口 music.audio() computer := Computer{ name: "HP", } music = computer //实体类赋值接口 music.audio() }
- 接口嵌套
接口可以通过嵌套,创建新的接口。列如: 飞鱼,既可以飞,又可以游泳。我们创建一个飞Fly接口,创建一个游泳接口,飞鱼接口有这两个接口组成
。
package main import "fmt" type Fly interface { flying() } type Swim interface { swimming() } type FlyFish interface { Fly Swim } type Fish struct { name string } func (f Fish) flying() { //实现飞的方法 fmt.Printf("%v,正在飞.....", f.name) } func (f Fish) swimming() { //实现游泳的方法 fmt.Printf("%v,正在游泳.....", f.name) } func main() { var fish FlyFish //定义接口 f := Fish{ name: "飞鱼", } fish = f //对接口进行赋值 fish.swimming() fish.flying() }
- 通过接口实现OCP设计原则
而面向对象的可复用设计的第一块基石,便是所谓的 开-闭
(Open-Closed Principle) 原则。虽然,go不是面向对象的语言,但也是可以模拟实现这个原则。对扩展是开放的,对修改是关闭的。
在本次测试中: 我们初设两个实现方法cat和dog,猫和狗此时并没有率属于人类结构体下,我们可以实现对人类结构体进行扩展的操作。
package main type Pet interface { eat() sleep() } type Dog struct { } type Cat struct { } //Dog实现接口 func (d Dog) eat() { println("Dog在eat....") } func (d Dog) sleep() { println("Dog在sleep....") } // Cat实现接口 func (c Cat) eat() { println("Cat在eat....") } func (c Cat) sleep() { println("Cat在sleep....") } type Person struct { } // pet既可以传递Dog也可以传递Cat func (p Person) care(pet Pet) { //接口接受 pet.eat() pet.sleep() } func main() { dog := Dog{} cat := Cat{} person := Person{} person.care(dog) //我们这里传递实体 person.care(cat) //我们这里传递实体 }
- 模拟OOP的属性和方法
Go没有面向对象的概念,也没有封装的概念。但是可以通过结构体 struct
和函数绑定
来实现OOP
的属性和方法特性。接收者receiver方法。通俗的讲: 就是属性和方法分开定义
列如: 想要定义一个Person类,有name和age属性,有 eat/sleep/work方法
package main import "fmt" type Person struct { name string age int } func (p Person) play() { fmt.Printf("%v\n正在玩游戏...", p.name) } func (p Person) Listener() { fmt.Printf("%v\n正在听歌...", p.name) } func main() { person := Person{ name: "吉士先生", age: 20, } person.play() person.Listener() }
7.Go继承
本质上没有oop的概念,也没有继承的概念,但是可以通过 结构体嵌套 实现这个特性。
内嵌结构体的话,我们可以省略调用内嵌结构体的变量名
package main import "fmt" type Animal struct { name string } func (a Animal) eat() { println("正在吃...") } func (a Animal) sleep() { fmt.Printf("%v正在睡...", a.name) } type Cat struct { //animal Animal //内嵌可以理解成继承的关系 Animal //内嵌结构体我们可以直接省略掉变量名 } func main() { cat := Cat{ Animal{ //因为上面省略了,所以我们这里也可以省略变量名 animal:=Animal{} name: "花花", }, } cat.sleep() // 直接调用,因为省掉变量名了 //cat.animal.sleep() //这里是不省略 }
- 构造函数
Go没有构造函数的概念,可以使用函数来模拟构造函数的功能。
利用函数来模拟构造函数...
package main import "fmt" type Person struct { name string age int } func NewPerson(name string, age int) (*Person, error) { if name == "" { return nil, fmt.Errorf("name 不能为空") } if age < 0 { return nil, fmt.Errorf("age 不能为负") } return &Person{ name: name, age: age, }, nil } func main() { person, err := NewPerson("李明", 20) fmt.Printf("%v", *person) fmt.Printf("%v", err) }
7.输出函数
格式化输出
%v 万能变量 %d 十进制整数 %f 浮点型 %s 字符串 %c 字符 %T 数据类型 %#v 详细万能变量 %p 指针 %t 布尔 &取地址 fmt.printf("%v",identify) ->格式化输出
换行输出
fmt.println()
不换行输出
fmt.print()
8.关系运算符和逻辑运算符和位运算符
- 关系运算符
1. ++和-- 不能放到表达式里面。只能先输出再调用。 ++ -- + - * / += -= /= > = < >= <=
2.逻辑运算符
&& 一个为假全为假 || 一个为真全为真 ! 真为假 假为真
3.位运算符
& : 一个为假全为假 | : 一个为真全为真 ^ : 不同为0,相同为1 << 左移 : 左边非0的保留,右边添加0 >> 右移 : 右边非0也不保留,
9.Go语言的流程控制
1.顺序
从上->倒下
- 条件判断
1. if语句判断执行流程 if 布尔表达式 { }else if 布尔表达式{ } else{ } (1).在Go语言中,表达式不需要用括号括起来。 (2).左括号{}必须存在if或else的同一行 (3).在if之后,条件语句之前,可以添加变量初始化语句,使用分割进行分割。 eg: if idenfied:=value;idenfied>20{} ---------------------- 2. switch进行条件判断默认是不穿透的。 3. Go语言switch语句,可以同时匹配多个条件,中间用逗号分割,有其中一个匹配成功即可。 switch idenfied{ case 1,2,3,4,5: println("工作日") default: println("休息日") } 4. Go语言的switch语句的case可以放置:判断表达式 5. fallthroug 设置穿透,Go语言默认是不穿透的。break打断穿透。0
- 循环
GO语言中只有for没有while{},do while{}
1. for 初始条件;条件表达式;结束语句{ 循环体 } 2. for表达式不需要加括号 3. 初始条件我们可以在外部定义。 4. 永真循环,就是我们的条件都不要。类似于while循环 for{} 或者 for ; ;{} ----------- 1. for index,value:=range 数组/字符串/map/chan{函数体} 2. 如果不需要的话,可以用匿名变量进行占位置 for i,v:=range identify{ }
10.Break与Continue与goto与标签💥
- Break
1. 单独在select中使用break和不使用break没有啥区别 2. 单独在表达式switch语句,并且没有fallthrough,使用break和不适用没有啥区别 3. 单独在表达式switch语句中,并且有fallthrough,使用break能够终止穿透 4. 带标签的break,可以跳出多层select/switch作用域,让break更加零花,不需要使用控制变量一层层的跳出循环,没有带break的只能跳出当前语句块。 (1).可以终止for循环 (2).可以打破switch的fallthrough穿透 (3).可以跳出标签
package main func main() { /** * 正常情况下,我们需要俩个break才能跳出双层循环。如果我们添加了标签就会直接跳转到外面,无需俩break */ MY_LABEL: //标签 for i := 0; i < 5; i++ { for j := 0; j < 5; j++ { if i == 2 { break MY_LABEL //标签 } println("你好") } println(i) } println("end....") }
- continue
continue
只能在循环中,在go中只能用for
循环中,它可以终止本次循环,进行下一次循环。在continue语句后添加标签时,表示开始标签对应的循环。
1. 在for循环中使用continue,会跳过此次循环,但不会终止后面的循环
3.goto
goto语句通过标签进行代码间的无条件跳转,goto语句可以在快速跳转循环、避免重复退出上有一定的帮助.Go语言中使用goto语句能够简化一些代码的实现过程。比如双层嵌套的for循环要退出时。
1. goto 标签名 与 break 标签名的区别 (1).break的标签名只能放在for循环上面,不能放在其他位置,goto的标签名可以随便放,不必只放在for寻黄傻瓜 (2).break的标签必须先定义再使用,goto可以先定义再使用也可以先使用再定义
goto 进行跳转
package main func main() { for i := 0; i < 5; i++ { for j := 0; j < 5; j++ { if i == 2 { goto first_range //标签的使用 } println("你好") } println(i) } println("end....") //这里是不会打印的,直接跳转 first_range: //标签的定义 println("end2....") }
- 标签的定义和使用
- break调用标签的话,必须使用在for循环之上。必须先定义后使用
- goto调用标签的话,可以先使用再调用,不必须在for循环下。位置随便放
- goto标签,如果goto跳转之后会直接跳转到标签所在的位置
- break标签,会退出循环。
1. 定义 标签名: 2. 使用 break 标签名 goto 标签名