共计 2416 个字符,预计需要花费 7 分钟才能阅读完成。
前言
我的读者中应该大部分都是 Java
从业者,不晓得写 Java
这些年是否真的有找到对象?
没找到也没关系,总不能在一棵树上吊死,咱们也能够来 Go
这边看看,说不定会有新发现。
开个玩笑,本文会以一个 Javaer
的角度来聊聊 Go
语言中的面向对象。
<!–more–>
OOP
面向对象这一词来源于Object Oriented Programming
,也就是大家常说的 OOP
。
对于 Go
是否为面向对象的编程语言,这点也是探讨已久;不过咱们能够先看看官网的说法:
其余的咱们暂且不看,Yes and No.
这个答复就比拟奥妙了,为了这篇文章还能写下去咱们先认为 Go
是面向对象的。
面向对象有着三个重要特色:
- 封装
- 继承
- 多态
封装
Go
并没有 Class
的概念,却能够应用 struct
来达到相似的成果,比方咱们能够对汽车申明如下:
type Car struct {
Name string
Price float32
}
与 Java
不同的是,struct
中只存储数据,不能定义行为,也就是办法。
当然也能为 Car
定义方法,只是写法略有不同:
func (car *Car) Info() {fmt.Printf("%v price: [%v]", car.Name, car.Price)
}
func main() {
car := Car{
Name: "BMW",
Price: 100.0,
}
car.Info()}
在办法名称前加上 (car *Car)
便能将该办法指定给 Car
,其中的 car
参数能够了解为 Java
中的 this
以及 Python
中的 self
,就语义来说我感觉 go
更加简略一些。
毕竟我见过不少刚学习 Java
的萌新十分不了解 this
的含意与用法。
匿名构造体
既然谈到构造体了那就不得不聊聊 Go
反对的匿名构造体(尽管和面向对象没有太大关系)
func upload(path string) {body, err := ioutil.ReadAll(res.Body)
smsRes := struct {
Success bool `json:"success"`
Code string `json:"code"`
Message string `json:"message"`
Data struct {URL string `json:"url"`} `json:"data"`
RequestID string `json:"RequestId"`
}{}
err = json.Unmarshal(body, &smsRes)
fmt.Printf(smsRes.Message)
}
Go
容许咱们在办法外部创立一个匿名的构造体,后续还能间接应用该构造体来获取数据。
这点在咱们调用内部接口解析响应数据时十分有用,创立一个长期的构造体也不必额为保护;同时还能用面向对象的形式获取数据。
相比于将数据寄存在 map
中用字段名获取要优雅许多。
继承
Go
语言中并没有 Java
、C++
这样的继承概念,类之间的关系更加扁平简洁。
各位 Javaer
应该都看过这类图:
置信大部分老手看到这图时就曾经懵逼,更别说钻研各个类之间的关系了。
不过这样益处也显著:如果咱们形象正当,整个系统结构会很好保护和扩大;但前提是咱们能形象正当。
在 Go
语言中更举荐应用组合的形式来复用数据:
type ElectricCar struct {
Car
Battery int32
}
func main() {
xp := ElectricCar{Car{Name: "xp", Price: 200},
70,
}
fmt.Println(xp.Name)
}
这样咱们便能够将公共局部的数据组合到新的 struct
中,并可能间接应用。
接口(多态)
面向接口编程的益处这里就不在赘述了,咱们来看看 Go 是如何实现的:
type ElectricCar struct {
Car
Battery int32
}
type PetrolCar struct {
Car
Gasoline int32
}
// 定义一个接口
type RunService interface {Run()
}
// 实现 1
func (car *PetrolCar) Run() {fmt.Printf("%s PetrolCar run \n", car.Name)
}
// 实现 2
func (car *ElectricCar)Run() {fmt.Printf("%s ElectricCar run \n", car.Name)
}
func Do(run RunService) {run.Run()
}
func main() {
xp := ElectricCar{Car{Name: "xp", Price: 200},
70,
}
petrolCar := PetrolCar{Car{Name: "BMW", Price: 300},
50,
}
Do(&xp)
Do(&petrolCar)
}
首先定义了一个接口 RunService
;ElectricCar
与 PetrolCar
都实现了该接口。
能够看到 Go
实现一个接口的形式并不是 implement
,而是用构造体申明一个雷同签名的办法。
这种实现模式被称为”鸭子类型“,Python
中的接口也是相似的 鸭子类型
。
具体介绍能够参考这篇:Python 中的面向接口编程
接口当然也是能够扩大的,相似于 struct
中的嵌套:
type DiService interface {Di()
}
// 定义一个接口
type RunService interface {
DiService
Run()}
得益于 Go
的强类型,方才的 struct
也得实现 DiService
这个接口能力编译通过。
总结
到这里应该是能了解官网所说的 Yes and No.
的含意了;Go
对面向对象的语法不像 Java
那么严苛,甚至整个语言中都找不到 object(对象)
这个关键词;然而利用 Go
里的其余个性也是能实现 OOP
的。
是否为面向对象我感觉并不重要,次要目标是咱们能写出易扩大好保护的代码。
例如官网规范库中就有许多利用接口编程的例子:
因为公司技术栈当初次要由 Go
为主,后续也会持续更新 Go
相干的实战经验;如果你也对学习 Go
感兴趣那无妨点个关注吧。