Go语言中的面向对象
面向对象的概念
洗衣服过程剖析:
- 给洗衣机里加脏衣服和洗衣粉。
- 启动洗衣机。
- 洗衣机自动注水,然后滚动。
- 脏衣服从黑颜色变成白颜色。
- 洗衣机自动停止。
用面向过程的思想实现代码。
//准备洗衣服
//输入参数:
//powder 洗衣机里放多少洗衣粉
//closes 洗衣机里放多少衣服
//clean 衣服是否是干净的
//返回值:
//洗衣机是否开启
//准备洗多少衣服
func prepare(powder int, closes int, clean bool) (bool, int) {
if powder <= 0 || closes <= 0 || clean == true {
return false, 0
}
return true, closes
}
//开始洗衣服
//输入参数:
//washer_state 洗衣机是否开启
//closes 准备洗多少衣服
//返回值:
//衣服是否是干净的
//洗了多少衣服
//洗衣机是否开启
func wash(washer_state bool, closes int) (bool, int, bool) {
if washer_state == false {
return false, 0, false
} else {
fmt.Println("注水")
fmt.Println("滚动")
fmt.Println("关机")
return true, closes, false
}
}
//检查最终状态
//输入参数:
//clean 衣服是否是干净的
//closes 洗了多少衣服
//washer_state 洗衣机是否开启
func check(clean bool, closes int, washer_state bool) {
if clean && closes > 0 {
fmt.Printf("洗干净了%d件衣服\n", closes)
if washer_state {
fmt.Println("你忘关洗衣机了")
}
} else {
fmt.Println("洗衣失败")
}
}
//整个洗衣服的过程
func WashProcedure(powder, closes int) {
washer_state := false
clean := false
washer_state, closes = prepare(powder, closes, clean)
clean, closes, washer_state = wash(washer_state, closes)
check(clean, closes, washer_state)
}
面向过程编程整个过程分为若干步,每一步对应一个函数,函数之间要传递大量的参数。
面向对象编程把大量参数封装到一个结构体里面,给结构体赋予方法,方法里面去修改结构体的成员变量。
go语言面向对象的好处:打包参数,继承,面向接口编程。
//洗衣机
type Washer struct {
State bool
Powder int
}
//衣服
type Closes struct {
Clean bool
}
func (washer *Washer) prepare(closes []*Closes) error {
if washer.State == true || washer.Powder <= 0 || len(closes) <= 0 {
return errors.New("请确保在关机的状态下加入适量衣物和洗衣粉")
}
return nil
}
func (washer *Washer) wash(closes []*Closes) error {
if err := washer.prepare(closes); err != nil {
return err
}
fmt.Println("开机")
washer.State = true
//检查是否有脏衣服
clean := true
for _, ele := range closes {
if ele.Clean == false {
clean = false
break
}
}
if clean {
washer.State = false
return errors.New("所有衣服都是干净的,不需要洗")
}
//开始洗衣服
fmt.Println("注水")
fmt.Println("滚动")
fmt.Println("关机")
washer.State = false
for _, ele := range closes {
ele.Clean = true
}
return nil
}
func (washer *Washer) check(err error, closes []*Closes) {
if err != nil {
fmt.Printf("洗衣失败:%v\n", err)
} else {
fmt.Printf("洗干净了%d件衣服\n", len(closes))
if washer.State == true {
fmt.Println("你忘关洗衣机了")
}
}
}
构造函数
定义User结构体。
type User struct {
Name string //""表示未知
Age int //-1表示未知
Sex byte //1男,2女,3未知
}
u := User{}
构造一个空的User,各字段都取相应数据类型的默认值。up := new(User)
构造一个空的User,并返回其指针。
自定义构造函数
func NewDefaultUser() *User {
return &User{
Name: "",
Age: -1,
Sex: 3,
}
}
func NewUser(name string, age int, sex byte) *User {
return &User{
Name: name,
Age: age,
Sex: sex,
}
}
单例模式
确保在并发的情况下,整个进程里只会创建struct的一个实例。
使用sync.Once保证只执行一次
var (
sUser *User
uOnce sync.Once
)
func GetUserInstance() *User {
uOnce.Do(func() { //确保即使在并发的情况下,下面的3行代码在整个go进程里只会被执行一次
if sUser == nil {
sUser = NewDefaultUser()
}
})
return sUser
}
//调用GetUserInstance()得到的是同一个User实例
su1 := GetUserInstance()
su2 := GetUserInstance()
//修改su1会影响su2
继承与重写
通过嵌入匿名结构体,变相实现“继承”的功能,因为访问匿名成员时可以跳过成员名直接访问它的内部成员。
type Plane struct {
color string
}
type Bird struct {
Plane
}
bird := Bird {}
bird.Plane.color
bird.color
重写
func (plane Plane) fly() int {
return 500
}
//重写父类(Plane)的fly方法
func (bird Bird) fly() int {
return bird.Plane.fly()+100 //调用父类的方法
}
正规来讲,Go语言并不支持继承,它只是支持组合。
type Plane struct {}
type Car struct{}
//Bird组合了Plane和Car的功能
type Bird struct {
Plane
Car
}
泛型
在有泛型之前,同样的功能需要为不同的参数类型单独实现一个函数。
func add4int(a, b int) int {
return a + b
}
func add4float32(a, b float32) float32 {
return a + b
}
func add4string(a, b string) string {
return a + b
}
使用泛型
type Addable interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64 | complex64 | complex128 | string
}
func add[T Addable](a,b T)T{
return a+b
}
go1.18正式支持泛型,但是Go语言之父Rob Pike建议不在Go 1.18的标准库中使用泛型。
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/17761402.html