7

同样都是使用接口,JAVA和Go差距咋就这么大呢?

 3 years ago
source link: https://studygolang.com/articles/35075
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

同样都是使用接口,JAVA和Go差距咋就这么大呢?

13161658867 · 大约16小时之前 · 383 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    

这篇文章将描述代码中经常使用的抢占式接口模式,以及为什么我认为在Go中遵循这种模式通常是不正确的。

什么是抢占式接口

接口是一种描述行为的方式,存在于大多数类型语言中。抢占式接口是指开发人员在实际需要出现之前对接口进行编码。一个示例可能如下所示。

type Auth interface {
  GetUser() (User, error)
}

type authImpl struct {
  // ...
}
func NewAuth() Auth {
  return &authImpl
}

抢占式接口何时有用

抢占接口通常用于在Java中,并且大获成功,这是大部分程序员的想法。相信,很多Go开发者也是这么认为的。这种用法主要区别在于Java具有显式接口,而Go是隐式接口。让我们看一些示例Java代码,这些代码显示了如果不使用Java中的抢占式接口可能会出现的困难。

// auth.java
public class Auth {
  public boolean canAction() {
    // ...
  }
}
// logic.java
public class Logic {
  public void takeAction(Auth a) {
    // ...
  }
}

现在假设您要更改Logic的takeAction方法中的参数Auth类型的对象,只要它具有canAction()方法即可。不幸的是,你不能。Auth没有在其中实现带有canAction()的接口。你现在必须修改Auth为其提供一个接口,然后您可以在takeAction中接受该接口,或者将Auth包装在一个除了实现的方法之外什么都不做的类中。即使logic.java定义了一个Auth接口以在takeAction()中接受,也可能很难让Auth实现该接口。您可能无权修改Auth,或者Auth可能位于第三方库中。也许Auth的作者不同意你的修改。也许在代码库中与同事共享Auth,现在需要在修改之前达成共识。这是希望的Java代码。

// auth.java
public interface Auth {
  public boolean canAction()
}
// authimpl.java
class AuthImpl implements Auth {
}
// logic.java
public class Logic {
  public void takeAction(Auth a) {
    // ...
  }
}

如果Auth的作者最初编码并返回一个接口,那么你在尝试扩展takeAction时,永远不会遇到问题。它自然适用于任何Auth接口。在具有显式接口的语言中,以后你会感谢过去的自己使用了抢占式接口。

为什么这在Go中不是问题

让我们在Go中设置相同的情况。

// auth.go 
type Auth struct { 
// ... 
}
// logic.go 
func TakeAction(a *Auth) { 
  // ... 
}

如果logic想要使TakeAction通用,则logic所有者可以单方面执行此操作,而不会打扰其他人。

// logic.go 
type LogicAuth interface { 
  CanAction() bool 
}
func TakeAction(a LogicAuth) { 
  // ... 
}

请注意 auth.go 不需要更改。这是使抢占式接口不再需要的关键所在。

Go中抢占式接口的意外副作用

Go的接口定义都是很小,但很强大。在标准库中,大多数接口定义都是单一方法。这允许最大的重用,因为实现接口很容易。当程序员对像上面的Auth这样的抢占式接口进行编码时,接口的方法数量往往会激增,这使得接口(可交换实现)的全部意义更难以实现。

Go中接口的最佳用法

Go的一个很好的经验法则是-接受接口,返回结构体。接受接口为您的API提供了最大的灵活性,返回结构体允许调用者快速导航到正确的函数。

即使你的Go代码接受结构体并返回结构体以启动,隐式接口也允许您稍后扩展你的API,而不会破坏向后兼容性。接口是一种抽象,抽象有时很有用。然而,不必要的抽象会造成不必要的复杂化。在需要之前不要使代码过于复杂。

3.jpg


有疑问加站长微信联系(非本文作者))

280

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK