Go 去找个对象吧

作者:神秘网友 发布时间:2021-02-23 17:20:13

Go 去找个对象吧

前言

我的读者中应该大部分都是 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. 【vue】计算属性

    前言 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的,比如简单的三元判断等。如果我们有一个变量是一段复杂的逻辑运算,写在了模板中,会让我们的模板看起来很笨重,而且需要时间理解这段代码到底写了什么如果多个地方使用到这个变量,还会让

  2. 基于 Java 的秒杀系统的开发

    前言 首先感谢大佬的无私奉献,愿意将自己的经验和技术分享给我们。贴上大佬的教程指北 教程页 经过了长达半个月的跟班学习,跟着老师做还用了这么长的时间,原因无非是自己对于知识的掌握不牢靠,知识面的狭窄。同时,在不断的学习和修改自己编写中出现的bu

  3. JS创建对象的几种模式

    Object构造函数模式 先创建空Object对象,再动态添加属性/方法 适用场景:起始时不确定对象内部数据 问题:语句太多 var obj={}obj.name="tom"obj.age=23 对象字面量模式 使用{}创建对象,同时指定属性/方法 适用场景:起始时对象内部数据是确定的 问题:如果创建

  4. 这一篇 Java 注解,写得太好了

    前言 Java注解是在JDK1.5被引入的技术,配合反射可以在运行期间处理注解,配合apt tool可以在编译器处理注解,在JDK1.6之后,apt tool被整合到了javac里面。 什么是注解 注解其实就是一种标记,常常用于代替冗余复杂的配置(XML、properties)又或者是编译器

  5. crontab按秒执行任务

    前言 某天开发给了一个需求,需要在后台持续运行两个php文件,间隔五秒。 大家都知道crontab定时任务设置时间,只能以 分 时 日 月 星 为单位设置,如何设置按秒执行计划任务? 解决方法: 我的解决方案是这样的:执行定时任务为每分钟执行一次,每次在执行

  6. nginx——mime.types使用案例

    前言: 以前只是知道nginx配置文件里面有一个mime.types,但是一直没有用到过,这段时间有需求用到了这个,给大家分享下mime.types的使用。 需求: 开发人员在开发过程中输出一些调试文件,但是这些文件都是服务器上面,开发没有权限登录服务器获取日志,然

  7. 使用shell实现php代码自动发布

    前言 在中小企业如果需要实现代码的自动化部署,99%以上公司不会开发什么自动化部署回滚平台的,这个时候就需要运维人员通过shell+开源软件比如jenkins来实现代码的自动化部署以及回滚。这里分享下我使用shell写的一个php代码自动部署脚本。大神勿喷。 脚本

  8. 使用shell脚本实现java灰度发布

    前言 在中小企业如果需要实现代码的自动化部署,99%以上公司不会开发什么自动化部署回滚平台的,这个时候就需要运维人员通过shell+开源软件比如jenkins来实现代码的自动化部署以及回滚。这里分享下我使用shell写的一个java代码自动部署脚本。大神勿喷。 脚本

  9. 安卓自动化打包(基于gradle)

    1 前言 2 编译环境安装 3 开始编译 4 每日自动打包实现 1. 前言 工作关系,需要做安卓环境的自动打包,领导要求公司产品、测试、开发等小伙伴每天来上班之前,可以在指定位置下载开发,测试,生产环境最新的安卓版本安装包,可以每日验证产品开发进度以及及

  10. zabbix+percona的插件监控MySql

    1 前言 2 部署 3 监控结果展示 1. 前言 前段时间用了下zabbix+percona的插件监控MySql,感觉不错,内置了190多个监控项,40多个图形展示。对MySql的监控比较全面,自己导入模版之后稍微根据自己的需求进行修改就可以使用。 https://www.percona.com/doc/perc

每天更新java,php,javaScript,go,python,nodejs,vue,android,mysql等相关技术教程,教程由网友分享而来,欢迎大家分享IT技术教程到本站,帮助自己同时也帮助他人!

Copyright 2020, All Rights Reserved. Powered by 跳墙网(www.tqwba.com)|网站地图|关键词