我如何在Go中处理不同方法的对/的HTTP请求?

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

How can I handle http requests of different methods to / in Go?

问题

我正在尝试找出在Go中处理对“/”和仅“/”的请求的最佳方法,并以不同的方式处理不同的方法。这是我想出的最好的方法:

  1. package main
  2. import (
  3. "fmt"
  4. "html"
  5. "log"
  6. "net/http"
  7. )
  8. func main() {
  9. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  10. if r.URL.Path != "/" {
  11. http.NotFound(w, r)
  12. return
  13. }
  14. if r.Method == "GET" {
  15. fmt.Fprintf(w, "GET, %q", html.EscapeString(r.URL.Path))
  16. } else if r.Method == "POST" {
  17. fmt.Fprintf(w, "POST, %q", html.EscapeString(r.URL.Path))
  18. } else {
  19. http.Error(w, "Invalid request method.", 405)
  20. }
  21. })
  22. log.Fatal(http.ListenAndServe(":8080", nil))
  23. }

这是Go的惯用写法吗?这是我在标准http库中能做的最好的吗?我更喜欢像express或Sinatra那样做一些类似http.HandleGet("/", handler)的事情。有没有一个适合编写简单REST服务的好框架?web.go看起来很有吸引力,但似乎停滞不前。

谢谢你的建议。

英文:

I'm trying to figure out the best way to handle requests to / and only / in Go and handle different methods in different ways. Here's the best I've come up with:

  1. package main
  2. import (
  3. "fmt"
  4. "html"
  5. "log"
  6. "net/http"
  7. )
  8. func main() {
  9. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  10. if r.URL.Path != "/" {
  11. http.NotFound(w, r)
  12. return
  13. }
  14. if r.Method == "GET" {
  15. fmt.Fprintf(w, "GET, %q", html.EscapeString(r.URL.Path))
  16. } else if r.Method == "POST" {
  17. fmt.Fprintf(w, "POST, %q", html.EscapeString(r.URL.Path))
  18. } else {
  19. http.Error(w, "Invalid request method.", 405)
  20. }
  21. })
  22. log.Fatal(http.ListenAndServe(":8080", nil))
  23. }

Is this idiomatic Go? Is this the best I can do with the standard http lib? I'd much rather do something like http.HandleGet("/", handler) as in express or Sinatra. Is there a good framework for writing simple REST services? web.go looks attractive but appears stagnant.

Thank you for your advice.

答案1

得分: 125

为了确保只提供根目录服务:你正在做正确的事情。在某些情况下,您可能希望调用http.FileServer对象的ServeHttp方法,而不是调用NotFound;这取决于您是否还有其他要提供的杂项文件。

为了以不同的方式处理不同的方法:我的许多HTTP处理程序只包含像这样的switch语句:

  1. switch r.Method {
  2. case http.MethodGet:
  3. // 提供资源。
  4. case http.MethodPost:
  5. // 创建新记录。
  6. case http.MethodPut:
  7. // 更新现有记录。
  8. case http.MethodDelete:
  9. // 删除记录。
  10. default:
  11. http.Error(w, "不允许的方法", http.StatusMethodNotAllowed)
  12. }

当然,您可能会发现像gorilla这样的第三方包对您更好。

英文:

To ensure that you only serve the root: You're doing the right thing. In some cases you would want to call the ServeHttp method of an http.FileServer object instead of calling NotFound; it depends whether you have miscellaneous files that you want to serve as well.

To handle different methods differently: Many of my HTTP handlers contain nothing but a switch statement like this:

  1. switch r.Method {
  2. case http.MethodGet:
  3. // Serve the resource.
  4. case http.MethodPost:
  5. // Create a new record.
  6. case http.MethodPut:
  7. // Update an existing record.
  8. case http.MethodDelete:
  9. // Remove the record.
  10. default:
  11. http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  12. }

Of course, you may find that a third-party package like gorilla works better for you.

答案2

得分: 45

嗯,我实际上正准备睡觉,所以快速评论一下查看http://www.gorillatoolkit.org/pkg/mux,它非常好,并且可以做你想要的事情,只需查看文档。例如

  1. func main() {
  2. r := mux.NewRouter()
  3. r.HandleFunc("/", HomeHandler)
  4. r.HandleFunc("/products", ProductsHandler)
  5. r.HandleFunc("/articles", ArticlesHandler)
  6. http.Handle("/", r)
  7. }

  1. r.HandleFunc("/products", ProductsHandler).
  2. Host("www.domain.com").
  3. Methods("GET").
  4. Schemes("http")

以及许多其他可能性和执行上述操作的方法。

但我觉得有必要解决问题的另一部分,“这是我能做的最好的吗”。如果标准库有点太简单,一个很好的资源可以查看这里:https://github.com/golang/go/wiki/Projects#web-libraries(特别链接到Web库)。

英文:

eh, I was actually heading to bed and thus the quick comment on looking at http://www.gorillatoolkit.org/pkg/mux which is really nice and does what you want, just give the docs a look over. For example

  1. func main() {
  2. r := mux.NewRouter()
  3. r.HandleFunc("/", HomeHandler)
  4. r.HandleFunc("/products", ProductsHandler)
  5. r.HandleFunc("/articles", ArticlesHandler)
  6. http.Handle("/", r)
  7. }

and

  1. r.HandleFunc("/products", ProductsHandler).
  2. Host("www.domain.com").
  3. Methods("GET").
  4. Schemes("http")

and many other possibilities and ways to perform the above operations.

But I felt a need to address the other part of the question, "Is this the best I can do". If the std lib is a little too bare, a great resource to check out is here: https://github.com/golang/go/wiki/Projects#web-libraries (linked specifically to web libraries).

huangapple
  • 本文由 发表于 2013年3月6日 14:54:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/15240884.html
匿名

发表评论

匿名网友

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

确定