在Go语言中是否有可能编写一个“流畅”风格的API?

huangapple go评论80阅读模式
英文:

Is it possible to write a 'fluent' style api in go?

问题

几种其他语言具有“流畅”或链式调用风格的API,允许您进行如下调用:

public class CatMap : ClassMap<Cat>
{
  public CatMap()
  {
    Id(x => x.Id);
    Map(x => x.Name)
      .Length(16)
      .Not.Nullable();
    Map(x => x.Sex);
    References(x => x.Mate);
    HasMany(x => x.Kittens);
  }
}

值得注意的例子包括流畅的nhibernate,jquery方法链接等。这是一种常见(我会说非常受欢迎)的API设计模式。

问题:Go语法似乎不支持这种方式。

在Go中,您可以这样做:

var blah = X().Y().Thing().OtherThing()

...但是这样:

package main

import "n"

func main() {
    n.Log(":D")
    .Example()
    .Example
}

会导致:

> command-line-arguments
> ./app.go:7: syntax error: unexpected .

...基本上是因为Go会自动在行末插入分号。

有人知道是否有办法解决这个问题吗?

您是否可以在某种程度上禁用自动插入分号?

或者说在Go中这种类型的API是否不可能实现?

英文:

Several other languages have a 'fluent' or chained-invokation style of api, which allows you to do calls like this:

public class CatMap : ClassMap&lt;Cat&gt;
{
  public CatMap()
  {
    Id(x =&gt; x.Id);
    Map(x =&gt; x.Name)
      .Length(16)
      .Not.Nullable();
    Map(x =&gt; x.Sex);
    References(x =&gt; x.Mate);
    HasMany(x =&gt; x.Kittens);
  }
}

Notable examples include fluent nhibernate, jquery method chaining, etc. It's a common (and I'd say quite well loved) api design pattern.

Problem: The go syntax doesn't seem to support this.

You can do this in go:

var blah = X().Y().Thing().OtherThing()

...but this:

package main

import &quot;n&quot;

func main() {
	n.Log(&quot;:D&quot;)
    .Example()
    .Example
}

Results in:

&gt; command-line-arguments
&gt; ./app.go:7: syntax error: unexpected .

...basically, because go automatically inserts ;'s at the end of a line.

Anyone know if there's a way around this?

Can you disable the auto-; in a block somehow?

Or is this sort of api just not possible in go?

答案1

得分: 15

你可以重新格式化你的代码为

func main() {
    n.Log(":D").
    Example().
    Example
}

将句号放在行尾可以避免自动分号插入 - 它只会在标识符、字面量或闭合的括号/大括号之后发生。

英文:

You can reformat your code to

func main() {
    n.Log(&quot;:D&quot;).
    Example().
    Example
}

Putting the period at the end of the line avoids automatic semicolon insertion—it only happens after identifiers, literals or closing parens/braces.

答案2

得分: -3

请查看goproxy。我认为其中的一部分是流畅的。

proxy.OnRequest(goproxy.DstHostIs("www.reddit.com")).DoFunc(
    func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
        if h,_,_ := time.Now().Clock(); h >= 8 && h <= 17 {
            return r,goproxy.NewResponse(r,
                    goproxy.ContentTypeText,http.StatusForbidden,
                    "别浪费时间!")
        }
        return r,nil
})
英文:

Have a look at goproxy. I think some part of it are fluent.

proxy.OnRequest(goproxy.DstHostIs(&quot;www.reddit.com&quot;)).DoFunc(
    func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
        if h,_,_ := time.Now().Clock(); h &gt;= 8 &amp;&amp; h &lt;= 17 {
            return r,goproxy.NewResponse(r,
                    goproxy.ContentTypeText,http.StatusForbidden,
                    &quot;Don&#39;t waste your time!&quot;)
        }
        return r,nil
})

huangapple
  • 本文由 发表于 2013年4月19日 16:21:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/16100317.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定