处理 API 版本的惯用方式是什么?

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

What is the idiomatic way to handle api versions

问题

我正在创建一个用于移动应用的Go服务器。我需要支持多个API版本,以应对用户不更新应用的情况。版本控制的主要问题是根据移动应用的版本以正确的格式返回数据。

我看到有三种基本的方法可以实现这一点:
A. 一种方法是在"/"路径上设置一个路由处理程序,然后允许该函数解析URL以进行版本控制。
示例:

func main() {
http.HandleFunc("/", routes.ParseFullURI)
}

B. 使用像gorilla/mux这样的库来处理路由器中的模式,但我看到一些警告称这可能会导致性能下降。
示例:

  func main() {
            mux.HandleFunc("/{version:}/", routes.ParseVersionForHome)
            mux.HandleFunc("/{version:}/getData", routes.ParseVersionForGetData)
            mux.HandleFunc("/{version:}/otherCall", routes.ParseVersionForOtherCall)
            }

C. 使用不变的个别URL,但根据标头将其分为不同的版本。
示例:

func main() {
   http.HandleFunc("/", routes.ParseHeaderForVersionForHome)
   http.HandleFunc("/getData", routes.ParseHeaderForVersionForGetData)
   http.HandleFunc("/otherCall", routes.ParseHeaderForVersionForOtherCall)
}

我担心选项1在代码方面会太混乱。我担心选项2在性能方面会太慢,而且我担心选项3对客户端来说可能很难处理,或者由于版本没有明确标记而变得混乱。

哪种方法对于Go来说最符合惯例,并且能够在移动应用中获得最佳性能,因为该应用将经常进行轮询?

英文:

I'm creating a server in Go intended for a mobile app. I need to be able to support multiple versions of the API for cases were users don't update the app. The main concern with the versioning, is to return data in the correct format for the version of the mobile app.

I've seen that there are three basic ways to do this.
A. One way is by having one route handler on "/", and then allowing that function to parse the url for versioning.
Example:

func main() {
http.HandleFunc("/", routes.ParseFullURI)
}

B. Use a library such as gorilla/mux to handle patterns within the router, but I saw some warnings that this can be too slow.
Example:

  func main() {
            mux.HandleFunc("{version:}/", routes.ParseVersionForHome)
            mux.HandleFunc("{version:}/getData", routes.ParseVersionForGetDAta)
            mux.HandleFunc("{version:}/otherCall", routes.ParseVersionForOtherCall)
            }

C. Have individual urls that don't change, but based on the header, split into different versions.
Example:

func main() {
   http.HandleFunc("/", routes.ParseHeaderForVersionForHome)
   http.HandleFunc("/getData", routes.ParseHeaderForVersionForGetData)
   http.HandleFunc("/otherCall", routes.ParseHeaderForVersionForOtherCall)
}

I'm concerned that option 1 will be too messy code wise. I'm concerned that option 2 will be too slow performance wise, and I'm concerned that option 3 will be difficult for the client to handle, or will get confusing since the version isn't clearly labeled.

Which method is the most idiomatic for Go, and will result in the greatest performance for a mobile app which will be polling often?

答案1

得分: 6

有许多路由框架可以进行分组,比如使用echo(如果你想要速度的话,这是一个非常好的框架)

package main

import "github.com/labstack/echo"

func ping(c *echo.Context) {
    c.String(200, "pong")
}

func main() {
    e := echo.New()

    v1 := e.Group("/v1")
    v1.Get("/ping", ping)

    v2 := e.Group("/v2")
    v2.Get("/ping", ping)

    e.Run(":4444")
}

我认为这样写很清晰。

我确定还有许多其他框架也支持这样的功能。我知道martini框架肯定支持,但那不是一种惯用的框架...

英文:

There are many routing frameworks that allow for grouping, for instance with echo (a very good framework if you want speed)

package main

import "github.com/labstack/echo"

func ping(c *echo.Context) {
        c.String(200, "pong")
}

func main() {
        e := echo.New()

        v1 := e.Group("/v1")
        v1.Get("/ping", ping)

        v2 := e.Group("/v2")
        v2.Get("/ping", ping)

        e.Run(":4444")
}

I think this is quite clean.

I am sure many other frameworks allow for this. I know for a fact martini does, but that is not an idiomatic framework...

huangapple
  • 本文由 发表于 2015年4月22日 01:41:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/29779468.html
匿名

发表评论

匿名网友

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

确定