Go 语言编程

类型和接口

Go语言的类型定义非常接近于C语言中的结构(struct),甚至直接沿用了:struct关键字。相比而言,Go语言并没有直接沿袭C++和Java的传统去设计一个超级复杂的类型系统,不支持继承和重载,而只是支持了最基本的类型组合功能。

巧妙的是,虽然看起来支持的功能过于简洁,细用起来你却会发现,C++和Java使用那些复杂的类型系统实现的功能在Go语言中并不会出现无法表现的情况,这反而让人反思其他语言中引入这些复杂概念的必要性。我们在第3章中将详细描述Go语言的类型系统。

Go语言也不是简单的对面向对象开发语言做减法,它还引入了一个无比强大的“非侵入式”接口的概念,让开发者从以往对C++和Java开发中的接口管理问题中解脱出来。在C++中,我们通常会这样来确定接口和类型的关系:

// 抽象接口
interface IFly
{
  virtual void Fly()=0;
};

// 实现类
class Bird : public IFly
{
public:
    Bird()
{}
    virtual ~Bird()
{}
public:
  void Fly()
     {
      //以鸟的方式飞行
     }
  };

  void main()
  {
     IFly* pFly = new Bird();
     pFly->Fly();
     delete pFly;
  }

`

显然,在实现一个接口之前必须先定义该接口,并且将类型和接口紧密绑定,即接口的修改会影响到所有实现了该接口的类型,而Go语言的接口体系则避免了这类问题:

type Bird struct {
  ...
}

func (b *Bird) Fly() {
    //以鸟的方式飞行
}

我们在实现Bird类型时完全没有任何IFly的信息。我们可以在另外一个地方定义这个IFly接口:

type IFly interface {
    Fly()
}

这两者目前看起来完全没有关系,现在看看我们如何使用它们:

func main() {
  var fly IFly = new(Bird)
    fly.Fly()
}

可以看出,虽然Bird类型实现的时候,没有声明与接口IFly的关系,但接口和类型可以直接转换,甚至接口的定义都不用在类型定义之前,这种比较松散的对应关系可以大幅降低因为接口调整而导致的大量代码调整工作。