文章目录
- 前言
- 一、结构体
- 1.声明结构体
- 2.匿名结构体
- 二、类
- 1.封装及绑定
- 2.继承
- 3.多态及接口
- 4.类访问权限
- 总结
前言
go语言支持类的操作,但是没有class关键字,使用struct来模拟类、结构体。类支持封装、绑定方法、继承等
一、结构体
结构体是由零个或多个任意类型的值聚合成的实体,它可以用于将数据分组为一个单元而不是将它们中的每一个作为单独的值。
1.声明结构体
用关键字 type 和 struct 用来定义结构体。
type StructName struct{
FieldName type
}
2.匿名结构体
以在不创建新数据类型的情况下声明结构,直接给予变量赋值。
func main() {
ppl := struct {
name string
age int
gender string
score float64
}{}
fmt.Println(ppl.name)
ppl.name = "ppl"
fmt.Println(ppl.name)
}
完整代码
package main
import "fmt"
type Student struct {
// 定义结构体
name string
age int
gender string
score float64
}
func main() {
// 所有字段都写完整值value,可不写key
ppl := Student{
"ppl",
18,
"男",
60.5, // 最后一字段写上逗号,不然花括号}要同一行
}
// 修改值
ppl.name = "我的新名字哈哈哈"
fmt.Println(ppl)
// 部分字段有值时,需要写上:key:value,无值的默认为空值
ppl1 := Student{
name: "PPL",
score: 060.6,
}
fmt.Println(ppl1, "age:", ppl1.age, " gender:", ppl1.gender)
prt := &ppl1 // 指针
fmt.Println(prt.name)
fmt.Println((*prt).name)
// 匿名结构体
ppl2 := struct {
name string
age int
gender string
score float64
}{}
fmt.Println(ppl2.name)
ppl2.name = "ppl"
fmt.Println(ppl2.name)
}
二、类
1.封装及绑定
如下结构体模拟类,有着属性,绑定了Eat方法
type Person struct {
// 成员属性
name string
age int
gender string
score float64
}
// 类绑定方法,绑定后可使用成员属性
func (p Person) Eat() {
p.name = "gsxl"
fmt.Println("不使用指针 Eat func 修改为:", p.name)
}
注意使用指针时及不使用指针时的区别:
- 不使用指针修改:只会改变当前成员属性,原始属性不会改变
- 使用指针修改,原始属性也跟着改变
完整代码
package main
import "fmt"
type Person struct {
// 成员属性
name string
age int
gender string
score float64
}
// 类绑定方法,绑定后可使用成员属性
func (p Person) Eat() {
p.name = "gsxl"
fmt.Println("不使用指针 Eat func 修改为:", p.name)
}
func (p *Person) Work() {
p.name = "广深小龙"
fmt.Println("使用指针 Work func 修改为:", p.name)
}
func main() {
ppl := Person{
name: "ppl",
age: 18,
gender: "男",
score: 66.23,
}
// 不使用指针修改:只会改变当前成员属性,原始属性不会改变
ppl.Eat()
fmt.Println(ppl.name)
// 使用指针修改,原始属性也跟着改变
ppl.Work()
fmt.Println(ppl.name)
}
2.继承
1、类的继承,直接写超类名称
type Human struct {
// 超类/父类
name string
age int
gender string
}
type Teacher struct {
Human // 继承,直接写超类
school string
gender int
}
2、如果是这样不算是继承,是嵌套
type Human struct {
// 超类/父类
name string
age int
gender string
}
type Teacher struct {
h Human // 继承,直接写超类
school string
gender int
}
完整代码
package main
import "fmt"
type Human struct {
// 超类/父类
name string
age int
gender string
}
func (h *Human) Eat() {
fmt.Println("Eat func:", h.name)
}
type Student1 struct {
// 并非继承,只是嵌套类
h Human
school string
}
type Teacher struct {
Human // 继承,直接写超类
school string
gender int
}
func main() {
s := Student1{
h: Human{
name: "ppl",
age: 25,
gender: "男",
},
school: "广西大学",
}
s.h.Eat() // 嵌套调用
t := Teacher{}
t.name = "漂漂亮"
fmt.Println(t.name)
t.Eat() // 继承调用,我们在Teacher并没有创建Eat方法,但是被继承了默认创建了同名方法及属性
// 定义了相同的属性,只能调用自己的,如果想调用父类那么需要.父类.属性
fmt.Println("子类的gender:", t.gender)
fmt.Println("父类的gender:", t.Human.gender)
}
3.多态及接口
在学习多态前我们先了解下接口interface,支持任何类型。
1、interface
接口类型是一种抽象类型。通常用来接收任何类型参数,如下:
/*
1.关键字定义接口:interface
2.interface接收任意数据类型
*/
func checkType(values ...interface{}) {
for _, value := range values {
switch v := value.(type) {
case string:
fmt.Println("this type is string:", v)
case int:
fmt.Println("this type is int:", v)
case bool:
fmt.Println("this type is bool:", v)
default:
fmt.Println("this type is default:", v)
}
}
}
2、多态
多态可以理解:传入不同对象,调用相同方法,实现不同效果。
下面举个例子:猫、狗都属于动物都需要吃食物,那么接口中都调用了Eat(),猫与狗都有Eat()的方法,只是食物不一样,那么根据不同对象进行对应的Eat()。
package main
import "fmt"
/*
多态:传入不同对象,调用相同方法,实现不同效果
1.定义一个接口,设计好需要调用接口,可多个
2.任何实现了此接口,都可赋值,从而实现多态
*/
type Animal interface {
// 定义一个接口,接口可以多个函数,不可有实现
Eat()
}
type Dog struct {
name string
eat string
}
type Cat struct {
name string
eat string
}
func (d *Dog) Eat() {
fmt.Println("this is Dog eat", d.eat)
}
func (c *Cat) Eat() {
fmt.Println("this is Cat eat", c.eat)
}
func main() {
// 定义一个接口类变量
var eat Animal
// 动物狗
dog := Dog{
name: "小狗钱钱",
eat: "狗粮",
}
eat = &dog
eat.Eat()
// 动物猫
cat := Cat{
name: "招财猫",
eat: "猫粮",
}
eat = &cat
eat.Eat()
}
4.类访问权限
go语言中都是遵循以下规则:
- pubic:首字母大写 (对内外均可调用)
- private:首字母小写 (仅对内调用,不可被非自己包下调用)
总结
怎么看着结构体就是类,类就是结构体?如果你也有这种疑问那是很正常吧,因为前言说了使用结构体模拟类,实现了类的三大特点。
End