通过学习Golang而意识到的事情

非常感谢您阅读2020年Classi降临日历的第16天文章!

我是一名服务器端工程师@willsmile。最近,我开始对住房和汽车产生了兴趣,并且在考虑具体事例时,我意识到它们会“自然地”出现,这给我带来了一种“不自然”的感觉。

序言

考虑到本文标题,你可能会对“为什么要学习Golang”这个问题产生疑问,所以我将在下面的主题中详细解释我的学习目标。在此之前,我想提及一下我作为一个有1年9个月工作经验的人对今年的职业发展目标。

总之,今年我的目标是成为一个“复眼”人。这个词来源于加谷先生的知识复眼思考法(一本非常有趣的书,我强烈推荐),我想表达的是为了与拥有不同立场和专业的人顺畅地合作,要能够理解对方的观点和重要性,以及为什么要理解,并且能够采取行动来实现理解。

这个问题

为什么选择学习Go语言作为学习目标?

从上述目标出发,我希望学习一种与我在工作中主要使用的Ruby编程语言不同的风格的编程语言,并进行比较,以了解它们之间是否存在差异。

因此,我列出了以下作为可能的语言选择,但考虑到我经常使用的工具中有许多是基于Go的(例如,yay,direnv,Hugo),出于学习资源的丰富性考虑,我决定进一步学习Golang。

1. Golang(Go语言)
2. Elm语言
3. Haskell语言

怎样学习呢?

国家说来,我按照下面的四个阶段来设计自己的学习计划。(我现在处于第三个阶段)

    • 段階1:何かを作れるように,最低限必要な知識を公式ドキュメントから獲得すること

実際作ったものはこちらのツール(s2test: A Simple Smoke Test Tool)です.いまの自分からみると,とてもRubyらしくGolangを使ってしまった感があります.

段階2:Golangに関する面白い記事・講演ビデオを広く読む・見て,言語を作った・使っている人がどう思っているのか(言語の特徴)を知ること

スキマ時間の活用と学びの“冗長性”向上の観点から,この段階2をダラダラやるのは個人的にとても好きですが,効率を求める場合,この段階を一旦飛ばしてもいいと思います.

段階3:Golangに関する良い本を選んで,その中のGolang特徴である部分の内容を精読すること

実際読んでいる本は,こちら(The Go Programming Language)です.

段階4:上記の過程から学んだことを踏まえて,段階1で作ったものを作り直すこと

通过之前的学习,你意识到了什么?

总结起来,“有时候不能使用继承”的意思。以下详细解释了认识到这一点的过程。

在Golang中的”继承”

众所周知,Golang中并没有继承的概念(尤其是在面向对象编程的语境下)。取而代之的是嵌入结构体(Embedding)和接口(Interface),它们与继承类似(但并不完全相同,请勿混淆)。

结构体的嵌入

这是指在字面上,在结构体中嵌入结构体这一意思。

正如以下代码示例所示,通过在汽车(Motorcar)和自行车(Bicycle)中嵌入人工物(Artifact),可以使由人工物定义的制造商(Manufacturer)字段在汽车和自行车中可用。此外,处理人工物的方法也可以处理汽车和自行车。这样就构建了“准is-a关系”。

然而,需要注意的是,人工物虽然是独立的实体,但它存在于汽车(或自行车)内,并不能称为亲子关系。这一点可以从以下源代码中变量mc的声明和赋值方式(Artifact不能省略)中看出来。

package main

import "fmt"

type Artifact struct {
    Manufacturer string
}

type Motorcar struct {
    Artifact
    HorsePower int
}

type Bicycle struct {
    Artifact
    NormalSpeed int
}

func (a Artifact) Info() {
    fmt.Printf("Made by %s\n", a.Manufacturer)
}

func main() {
    mc := Motorcar{
        Artifact: Artifact{
            Manufacturer: "Toyota",
        },
        HorsePower: 100,
    }

    bc := Bicycle{}
    bc.Manufacturer = "Bianchi"
    bc.NormalSpeed = 20

    mc.Info()
    bc.Info()
}

界面 .

我发现要简洁地解释”接口是什么?”是很困难的,所以借用@tenntenn的话来解释。在Go语言中,”抽象化的概念只存在于接口”。在编程中,抽象化的目的是降低模块的耦合度,也就是关注点的分离。

根据以下代码的具体示例,我们将关注汽车(Motorcar)和自行车(Bicycle)的运输行为,并将其定义为交通工具(Vehicle)的接口。通过这样做,我们可以将汽车和自行车都视为能够运输的交通工具,暂时忽略它们各自具有的字段(马力,常速)和通过方法定义的运输处理方式(详细信息请参阅注释)。

package main

import "fmt"

type Motorcar struct {
    HorsePower int
}

type Bicycle struct {
    NormalSpeed int
}

type Vehicle interface {
    Transport()
}

func (m Motorcar) Transport() {
    // エンジンの性能による速度が決まる
    fmt.Printf("Moving by a motor which provides power of %d kW.\n", m.HorsePower)
}

func (b Bicycle) Transport() {
    // 車体の構造上の性質による速度が決まる
    fmt.Printf("Moving by a human and generally run at speed of %d km/h.\n", b.NormalSpeed)
}

func main() {
    var mc, bc Vehicle

    mc = Motorcar{
        HorsePower: 100,
    }

    bc = Bicycle{
        NormalSpeed: 20,
    }

    mc.Transport()
    bc.Transport()
}

究竟为什么呢?

在学习Golang结构体的嵌入和接口时,我脑海中浮现出了“为什么继承不可行?”和“为什么在设计语言时故意排除了继承?”这两个问题。经过一番调查研究,我意识到,“在某些情况下,使用继承会带来很大的缺点。”

由于详细解释答案会使得篇幅过长,故在此不再详细阐述。如果您想要详细了解,请推荐您阅读参考文献2(书籍,第6章:通过继承获取行为、第7章:通过模块共享角色行为)和3(文章)。

作者的评论

从这次经历中我学到的是,不管是编程语言还是人,在设计上都存在着不同的观点,也会持有不同的观点。与其将不同之处分为“喜欢”和“讨厌”,不如意识到这种差异,并思考其中的原因,这样可以获得有益的启示。

文献引用

    《エキスパートGo》是一本使用Ruby作为敏捷开发教程的实用面向对象设计的书籍,第二版。《君の継承の使い方は間違っている》询问Go是否是面向对象的语言。
广告
将在 10 秒后关闭
bannerAds