Golang 中的面向对象

image

前言

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

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

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

OOP

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

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

image

其他的我们暂且不看,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 应该都看过这类图:

image

相信大部分新手看到这图时就已经懵逼,更别说研究各个类之间的关系了。

不过这样好处也明显:如果我们抽象合理,整个系统结构会很好维护和扩展;但前提是我们能抽象合理。

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 中的接口也是类似的鸭子类型

image

详细介绍可以参考这篇:Python 中的面向接口编程

接口当然也是可以扩展的,类似于 struct 中的嵌套:

type DiService interface {
    Di()
}

//定义一个接口
type RunService interface {
    DiService
    Run()
}
image

得益于 Go 的强类型,刚才的 struct 也得实现 DiService 这个接口才能编译通过。

总结

到这里应该是能理解官方所说的 Yes and No. 的含义了;Go 对面向对象的语法不像 Java 那么严苛,甚至整个语言中都找不到 object(对象) 这个关键词;但是利用 Go 里的其他特性也是能实现 OOP 的。

是否为面向对象我觉得并不重要,主要目的是我们能写出易扩展好维护的代码。

例如官方标准库中就有许多利用接口编程的例子:

image

由于公司技术栈现在主要由 Go 为主,后续也会继续更新 Go 相关的实战经验;如果你也对学习 Go 感兴趣那不妨点个关注吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容