Go 去找个对象吧
前言
我的读者中应该大部分都是 Java
从业者,不知道写 Java
这些年是否真的有找到对象?
没找到也没关系,总不能在一棵树上吊死,我们也可以来 Go
这边看看,说不定会有新发现。
开个玩笑,本文会以一个 Javaer
的角度来聊聊 Go
语言中的面向对象。
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
感兴趣那不妨点个关注吧。
Go 去找个对象吧的更多相关文章
- php对象和数组的相互转换(还是可以去找没有没php的高阶课程看看看)(要不别人分析一下重点要点,要不自己来,不然 效果真的不好)
php对象和数组的相互转换(还是可以去找没有没php的高阶课程看看看)(要不别人分析一下重点要点,要不自己来,不然 效果真的不好) 一.总结 都是自己实现的函数 算法: 1.先判断类型,gettype ...
- 只要项目是maven构建的,pom.xml中依赖的jar包全都默认去你电脑本地仓库去找
只要项目是maven构建的,pom.xml中依赖的jar包全都默认去你电脑本地仓库去找
- 【spring boot】spring boot中使用@RestController不起作用,不返回json,依旧去找访问接口的请求地址对应的页面
问题描述: spring boot中使用@RestController不起作用,不返回json,依旧去找访问接口的请求地址对应的页面 表现结果: 1>使用postman测试接口,表现为返回是40 ...
- 【mybatis】idea中 mybatis的mapper类去找对应的mapper.xml中的方法,使用插件mybatis-plugin
idea中 mybatis的mapper类去找对应的mapper.xml中的方法,使用插件mybatis-plugin,名字可能叫Free mybatis-plugin 安装上之后,可能需要重启ide ...
- 花括号的使用 printf %${width}s , 否则会 去找 $widths
花括号的使用 printf %${width}s , 否则会 去找 $widths 1 #! /usr/bin/perl 2 use strict; 3 use warnings; 4 ...
- [Java.File]如果写 File filesFolder = new File("/") ,在windows系统中,filesFolder 会去找哪个盘符? 答案:程序运行路径的根盘符.
首先这段代码在Unix/Linux系统上会去找根路径,但在Windows系统上会去找C:盘还是D:盘还是其它盘呢? 其实它会去找user.dir所在盘符的根目录,user.dir即用户的当前工作目录, ...
- 程序猿看小说还要去找TXT?自己动手爬一个TXT才是正确的打开方式
前言 在贴吧看了个小说追了几天被删帖了,于是自己找书名,打算下载下来看,结果要么是需要充值,要么不提供下载.作为一个猿类,怎么能忍. 好在小说网站多入牛毛,有的采用js加载文字来防采集,有的用css图 ...
- 《JavaScript权威指南》学习笔记 第三天 找个对象
现实生活中真的对象没有找到,在JavaScript 里左一个对象又一个对象,搞的我也是晕晕乎乎不知所云.人事复杂,人心难懂.我虽然是文科生,但是也不善于巧言.还是在js里面找找对象吧.那么我们今天就从 ...
- Python学到什么程度就可以去找工作?掌握这4点足够了!
大家在学习Python的时候,有人会问“Python要学到什么程度才能出去找工作”,对于在Python培训机构学习Python的同学来说这都不是问题,因为按照Python课程大纲来,一般都不会有什么问 ...
随机推荐
- AJAX传值中文乱码
AJAX传值时采用的是UTF-8编码格式,客户端中文字符传输到服务器端时,如果服务器编码格式或者所采用的MVC框架的编码格式不是UTF-8,则很可能会出现中文乱码.解决办法如下: 客户端用js函数en ...
- 并发队列:ArrayBlockingQueue实际运用场景和原理
ArrayBlockingQueue实际应用场景 之前在某公司做过一款情绪识别的系统,这套系统通过调用摄像头接口采集人脸信息,将采集的人脸信息做人脸识别和情绪分析,最终经过一定的算法将个人情绪数据转化 ...
- php之bindValue和bindParam的区别
PDOStatement::bindValue - 把一个值绑定到一个参数 绑定一个值到用作预处理的 SQL 语句中的对应命名占位符或问号占位符. PDOStatement::bindParam - ...
- IDLE怎么将主题修改成Darcula样式?
摘要:每个人都有自己心中理想的编辑器主题,我更倾向于Darcula,你们呢? 想必没用过Darcula主题的朋友,会好奇它是何方神圣? 是不是很赏心悦目,代码这冰冷的东西也变得生龙活虎? 我最近在 ...
- Hive创建HBase,ES外部表
1.创建HBase外部表 CREATE EXTERNAL TABLE `ods_women`( `rowkey` string COMMENT 'from deserializer', `articl ...
- CF-1440C2 Binary Table (Hard Version) (构造,模拟)
Binary Table (Hard Version) 题意 \(n*m(2\le n,m\le 100)\) 的01矩阵,每次可以选择一个宽度为2的子矩阵,将四个位置中的任意3个进行翻转,即0变1, ...
- Atcoder(134)E - Sequence Decomposing
E - Sequence Decomposing Time Limit: 2 sec / Memory Limit: 1024 MB Score : 500500 points Problem Sta ...
- Codeforces Round #547 (Div. 3) D. Colored Boots (贪心,模拟)
题意:有两个字符串,两个字符串中的相同字符可以相互匹配,\(?\)可以和任意字符匹配,输出最大匹配的字符数量和它们分别两个字符串中的位置. 题解:很容易贪心,我们先遍历第一个字符串,然后在第二个字符串 ...
- Codeforces Round #680 (Div. 2, based on Moscow Team Olympiad) C. Division (数学)
题意:有两个数\(p\)和\(q\),找到一个最大的数\(x\),使得\(p\ mod\ x=0\)并且\(x\ mod\ q\ne 0\). 题解:首先,如果\(p\ mod\ q\ne0\),那么 ...
- Educational Codeforces Round 97 (Rated for Div. 2) C. Chef Monocarp (DP)
题意:有\(n\)个菜在烤箱中,每个时刻只能将一个菜从烤箱中拿出来,第\(i\)个时刻拿出来的贡献是\(|i-a[i]|\),你可以在任意时刻把菜拿出来,问将所有菜拿出的最小贡献是多少? 题解: 先对 ...