动态实例化 HandleFunc

Dynamically instantiating HandleFunc

我一直在努力以动态方式实施 HandleFunc()

我想在 Go 中将此 yaml 文件转换为本地 http 网络服务器。

# Example .mock.yaml config
Endpoints:
  - Resource: /city/1
    Method: GET
    Response: '{ Id": 1, "Name": "Albuquerque", "Population": 559.374, "State": "New Mexico" }'
    StatusCode: 200

  - Resource: /city
    Method: POST
    Response: '{ "Name": "Albuquerque", "Population": 559.374, "State": "New Mexico" }'
    statusCode: 200

  - Resource: /city/1
    Method: PUT
    Response: '{ "Population": 601.255 }'
    StatusCode: 204

  - Resource: /city/1
    Method: DELETE
    StatusCode: 204

现在我设法实现了以下内容:

package utils

import (
    "io"
    "net/http"

    "github.com/gorilla/mux"

    "github.com/bschaatsbergen/mock/model"
)

func StartServer(conf model.Config, port string) {
    r := mux.NewRouter()

    for _, endpoint := range conf.Endpoints {
        r.HandleFunc(endpoint.Resource, func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Content-Type", "application/json")
            w.WriteHeader(endpoint.StatusCOde)

            io.WriteString(w, endpoint.Response)
        }).Methods(endpoint.Method)
    }

    address := ":" + port

    http.ListenAndServe(address, r)
}

^https://play.golang.org/p/YoTTUKnQL_5

但这并没有削减它,因为它覆盖了之前创建的路由('/city/1' GET、DELETE 和 POST 是冲突的)。

如果有人可以帮助我了解如何将 yaml 配置动态转换为本地 Web 服务器,我们将不胜感激!

我引用@mkopriva,谢谢!

I'm fairly certain your problem is the same as the one here: whosebug.com/questions/69595865/…. i.e. All of your anon handler closures capture one and the same variable, the iteration variable, which, at the end of the loop, will hold the last element of the Endpoints slice. Correct? Can the question be closed as duplicate?

工作代码:

func StartServer(conf model.Config, port string) {
    r := mux.NewRouter()

    for _, endpoint := range conf.Endpoints {
        route := endpoint
        r.HandleFunc(route.Resource, func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Content-Type", "application/json")
            w.WriteHeader(route.Statuscode)
            io.WriteString(w, route.Response)
        }).Methods(route.Method)
    }

    address := ":" + port

    log.Fatal(http.ListenAndServe(address, r))
}