前言

我的读者中应该大部分都是 Java 从业者,不知道写 Java 这些年是否真的有找到对象?

没找到也没关系,总不能在一棵树上吊死,我们也可以来 Go 这边看看,说不定会有新发现。

开个玩笑,本文会以一个 Javaer 的角度来聊聊 Go 语言中的面向对象。

OOP

面向对象这一词来源于Object Oriented Programming,也就是大家常说的 OOP

对于 Go 是否为面向对象的编程语言,这点也是讨论已久;不过我们可以先看看官方的说法:

其他的我们暂且不看,Yes and No. 这个回答就比较微妙了,为了这篇文章还能写下去我们先认为 Go 是面向对象的。


面向对象有着三个重要特征:

  1. 封装
  2. 继承
  3. 多态

封装

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 语言中并没有 JavaC++ 这样的继承概念,类之间的关系更加扁平简洁。

各位 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) }

首先定义了一个接口 RunServiceElectricCarPetrolCar 都实现了该接口。

可以看到 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 去找个对象吧的更多相关文章

  1. php对象和数组的相互转换(还是可以去找没有没php的高阶课程看看看)(要不别人分析一下重点要点,要不自己来,不然 效果真的不好)

    php对象和数组的相互转换(还是可以去找没有没php的高阶课程看看看)(要不别人分析一下重点要点,要不自己来,不然 效果真的不好) 一.总结 都是自己实现的函数 算法: 1.先判断类型,gettype ...

  2. 只要项目是maven构建的,pom.xml中依赖的jar包全都默认去你电脑本地仓库去找

    只要项目是maven构建的,pom.xml中依赖的jar包全都默认去你电脑本地仓库去找

  3. 【spring boot】spring boot中使用@RestController不起作用,不返回json,依旧去找访问接口的请求地址对应的页面

    问题描述: spring boot中使用@RestController不起作用,不返回json,依旧去找访问接口的请求地址对应的页面 表现结果: 1>使用postman测试接口,表现为返回是40 ...

  4. 【mybatis】idea中 mybatis的mapper类去找对应的mapper.xml中的方法,使用插件mybatis-plugin

    idea中 mybatis的mapper类去找对应的mapper.xml中的方法,使用插件mybatis-plugin,名字可能叫Free mybatis-plugin 安装上之后,可能需要重启ide ...

  5. 花括号的使用 printf %${width}s , 否则会 去找 $widths

    花括号的使用  printf %${width}s , 否则会 去找  $widths 1 #! /usr/bin/perl   2 use strict;  3 use warnings;  4   ...

  6. [Java.File]如果写 File filesFolder = new File("/") ,在windows系统中,filesFolder 会去找哪个盘符? 答案:程序运行路径的根盘符.

    首先这段代码在Unix/Linux系统上会去找根路径,但在Windows系统上会去找C:盘还是D:盘还是其它盘呢? 其实它会去找user.dir所在盘符的根目录,user.dir即用户的当前工作目录, ...

  7. 程序猿看小说还要去找TXT?自己动手爬一个TXT才是正确的打开方式

    前言 在贴吧看了个小说追了几天被删帖了,于是自己找书名,打算下载下来看,结果要么是需要充值,要么不提供下载.作为一个猿类,怎么能忍. 好在小说网站多入牛毛,有的采用js加载文字来防采集,有的用css图 ...

  8. 《JavaScript权威指南》学习笔记 第三天 找个对象

    现实生活中真的对象没有找到,在JavaScript 里左一个对象又一个对象,搞的我也是晕晕乎乎不知所云.人事复杂,人心难懂.我虽然是文科生,但是也不善于巧言.还是在js里面找找对象吧.那么我们今天就从 ...

  9. Python学到什么程度就可以去找工作?掌握这4点足够了!

    大家在学习Python的时候,有人会问“Python要学到什么程度才能出去找工作”,对于在Python培训机构学习Python的同学来说这都不是问题,因为按照Python课程大纲来,一般都不会有什么问 ...

  10. Python学到什么程度才可以去找工作?掌握这4点足够了!

    大家在学习Python的时候,有人会问"Python要学到什么程度才能出去找工作",对于在Python培训机构学习Python的同学来说这都不是问题,因为按照Python课程大纲来 ...

随机推荐

  1. 转载 NPOI Excel 单元格背景颜色对照表

    NPOI Excel 单元格颜色对照表,在引用了 NPOI.dll 后可通过 ICellStyle 接口的 FillForegroundColor 属性实现 Excel 单元格的背景色设置,FillP ...

  2. localResizeIMG

    http://think2011.net/localResizeIMG/test/ 演示一下 自己试试 点我直接进入演示页面 说明 在客户端压缩好要上传的图片可以节省带宽更快的发送给后端,特别适合在移 ...

  3. Reverse Integer (JAVA)

    public class Solution { public int reverse(int x) { StringBuffer sb = new StringBuffer(x+"" ...

  4. vijos 1115 火星人

    说了那么多.事实上就是遍历全排列 #include<iostream> #include<cstdio> #include<algorithm> #include& ...

  5. SEAndroid安全机制中的进程安全上下文关联分析

    前面一篇文章分析了文件安全上下文关联过程.可是在SEAndroid中,除了要给文件关联安全上下文外,还须要给进程关联安全上下文.由于仅仅有当进程和文件都关联安全上下文之后,SEAndroid安全策略才 ...

  6. 3.JAVA-方法重载,类的封装,构造/析构方法

    1.方法重载 和C++的函数重载一样,主要是实现多个相同的函数名,但是参数表不同. 参数表不同主要有以下几种 1) 参数个数不同 2) 参数类型不同 3) 参数顺序不同 2.类和对象 类class 用 ...

  7. Springboot 系列(九)使用 Spring JDBC 和 Druid 数据源监控

    前言 作为一名 Java 开发者,相信对 JDBC(Java Data Base Connectivity)是不会陌生的,JDBC作为 Java 基础内容,它提供了一种基准,据此可以构建更高级的工具和 ...

  8. AttributeError: &#39;NoneType&#39; object has no attribute &#39;split&#39; 报错处理

    报错场景 social_django 组件对原生 django 的支持较好, 但是因为 在此DRF进行的验证为 JWT 方式 和 django 的验证存在区别, 因此需要进行更改自行支持 JWT 方式 ...

  9. 模块热替换 HMR

    devserver:{hot:true},既及时更新代码,样式(需配合loader)变化,自动重编译,只适用于开发环境. 入口文件中,添加监视: + if (module.hot) {+ module ...

  10. Splunk Web页面的登录密码忘记了怎么办

    splunk的web登录密码忘记的话,可以使用以下方法重置. 一.关闭splunk服务 /opt/splunk/bin/splunk stop 二.删除默认密码配置文件 三.重启启动splunk服务, ...