Go Impossible Missions

主要就是为了吐槽 GO

模板方法

在绝大多数的 OOP 语言中,我们都希望,我们可能在父类中完成绝大多数的任务,子类仅仅完成一部分的任务即可。

1
2
3
4
5
6
7
public interface Named {
String name();

default String firstName() {
return name().split("/")[0];
}
}

当我们实现 ENCN 的版本时候,只需要。

1
2
3
4
5
6
class EnglishNamed implements Named{
@Override
public String name() {
return "jack/ma";
}
}
1
2
3
4
5
6
class ChineseNamed implements Named {
@Override
public String name() {
return "春/天";
}
}

对于获取 FirstName 的逻辑是一致的。

那如果我们使用 GO 来实现的话。

1
2
3
4
5
6
7
8
9
10
type EnglishNamed struct {
}

func (e *EnglishNamed) Name() string {
return "jack/ma"
}

func (e *EnglishNamed) FirstName() string {
return strings.Split(e.Name(), "/")[0]
}
1
2
3
4
5
6
7
8
9
10
11
type ChineseNamed struct {
}

func (e *ChineseNamed) Name() string {
return "jack/ma"
}

func (e *ChineseNamed) FirstName() string {
return strings.Split(e.Name(), "/")[0]
}

我们发现其实我们有一个 重复的 代码。为了让这个代码不重复,单纯的依靠组合不能够达成。我们需要修改下实现的方式,重新定义

1
2
3
4
5
6
7
8
9
type Name string

type Named interface {
Name() Name
}

func (n Name) FirstName() string {
return strings.Split(string(n), "/")[0]
}

然后我们再来实现对象

1
2
3
4
5
6
type EnglishNamed struct {
}

func (e *EnglishNamed) Name() Name {
return "jack/ma"
}
1
2
3
4
5
6
type ChineseNamed struct {
}

func (e *ChineseNamed) Name() Name {
return "jack/ma"
}

使用 Rust 我们可以实现和 Java 类似的代码。go 缺失在 inteface 没有 default method

Deep Equal

我们经常会有这么一个需求,比如我有一个对象 A,包含了对象 B,又包含了对象 C,我希望 C.xxx 字段如果是 True 就进行一些处理

基础定义
1
2
3
4
5
6
7
8
9
10
11
type A struct {
B *B
}

type B struct {
C *C
}

type C struct {
Flag bool
}

如果是 go 只能写出如下代码

1
2
3
4
5
func ifDo(a *A) {
if a != nil && a.B != nil && a.B.C != nil && a.B.C.Flag {
//Do something
}
}

而对比之下,Java 可以写出略微优雅的代码

1
2
3
4
5
6
7
public void ifDo(A a){
Boolean ifCondition = Optional.ofNullable(a)
.map(A::getB)
.map(B::getC)
.map(C::isFlag)
.orElse(false);
}

而到了 Rust | kotlin 我们可以借助于语法糖

1
2
3
4
5
6
7
8
fn doIf(a: Option<A>) -> Option<bool> {
match a?.b?.c {
Some(it) => {
return Option::Some(it.flag);
}
_ => Option::None
}
}