当处理程序在主包外部定义时 chi.URLParam 不起作用

Bla*_*Cat 13 go go-chi

所以我是新手,目前我尝试使用 chi 构建一个小 REST-API(我喜欢它)。昨天我遇到了一个问题,我不太明白。

在我的小测试项目中,我有一个main.go文件,其中包含路由器实例化、添加中间件和启动服务器的主要功能:

func main() {
    router := chi.NewRouter()
    // Middleware
    router.Use(middleware.RequestID)
    router.Use(middleware.RealIP)
    router.Use(middleware.Logger)
    router.Use(middleware.Recoverer)
    // Routes
    router.Post("/login", users.Login)
    router.Post("/register", users.Register)
    router.With(users.LoginRequired).Route("/users", func(r chi.Router) {
        r.Get("/{user_id}", users.GetUser)
    })
    // Start Server
    port := ":8080"
    log.Printf("Server starting at port %v\n", port)
    log.Fatal(http.ListenAndServe(port, router))
}
Run Code Online (Sandbox Code Playgroud)

首先,问题不存在,因为我在main.go文件中定义了所有处理程序函数,并且 GetUser 函数按预期工作并从我的“数据库”(包含 3 个用户的数组)返回一个用户:

func GetUser(w http.ResponseWriter, r *http.Request) {
    uID := chi.URLParam(r, "user_id") // Problem when not in main -> uID = ""
    id, err := strconv.Atoi(uID)
    if err != nil {
        log.Printf("Error while parsing int: %v\n", err)
        // TODO: return error 400
    }
    user := DataBase[id-1]
    response, err := json.Marshal(user)

    if err != nil {
        log.Printf("Error while marshalling user: %v\n", err)
    }
    w.Write(response)
}
Run Code Online (Sandbox Code Playgroud)

一旦我将此函数从文件中移出main.go到另一个名为userschi.URLParam 的包中,函数就会返回一个空字符串,并且无法再找到 URLParam。我读到它与上下文有关,但我无法理解如果我想使用 chi 函数,我必须将函数放在主文件中。

我错过了什么吗?

更新

按照要求,我删除了除 GetUser 函数之外的所有内容。我的 main.go 文件目前如下所示:

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "strconv"

    "github.com/MyUserName/MyProjectName/internals/users"
    "github.com/go-chi/chi/v5"
)

func GetUser(w http.ResponseWriter, r *http.Request) {

    id, err := strconv.Atoi(chi.URLParam(r, "user_id"))
    if err != nil {
        log.Printf("Error while parsing int: %v\n", err)
        // TODO: return error 400
    }
    log.Printf("ID=%v, Current Database=%v\n", id, users.DataBase)
    user := users.DataBase[id-1]
    response, err := json.Marshal(user)

    if err != nil {
        log.Printf("Error while marshalling user: %v\n", err)
    }
    w.Write(response)
}

func main() {
    router := chi.NewRouter()
    // Routes
    router.Get("/users/{user_id}", GetUser)
    // Start Server
    port := ":8080"
    log.Printf("Server starting at port %v\n", port)
    log.Fatal(http.ListenAndServe(port, router))
}
Run Code Online (Sandbox Code Playgroud)

我的用户包如下所示:

package users

import (
    "encoding/json"
    "log"
    "net/http"
    "strconv"

    "github.com/MyUserName/MyProjectName/internals/models"
    "github.com/go-chi/chi"
)

var (
    DataBase = make([]models.User, 0)
)

func GetUser(w http.ResponseWriter, r *http.Request) {

    id, err := strconv.Atoi(chi.URLParam(r, "user_id"))
    if err != nil {
        log.Printf("Error while parsing int: %v\n", err)
        // TODO: return error 400
    }
    log.Printf("ID=%v, Current Database=%v\n", id, DataBase)
    user := DataBase[id-1]
    response, err := json.Marshal(user)

    if err != nil {
        log.Printf("Error while marshalling user: %v\n", err)
    }
    w.Write(response)
}

func init() {
    initUser := []models.User{
        {
            ID:       1,
            UserName: "john",
            Password: "doe",
        },
        {
            ID:       2,
            UserName: "max",
            Password: "mustermann",
        },
        {
            ID:       3,
            UserName: "jane",
            Password: "doe",
        },
    }
    for _, user := range initUser {
        DataBase = append(DataBase, user)
    }
    log.Println("Initializing Database")
}
Run Code Online (Sandbox Code Playgroud)

当我使用 users 包中的函数时,它不起作用,并且仍然是一个空字符串,如果我使用 main.go 文件中的函数,它会起作用。

更新

所以显然我太愚蠢了,两次导入相同的包。在我的主文件中,我使用了“github.com/go-chi/chi/v5”,在我的用户包中,我使用了“github.com/go-chi/chi”。使用同样的方法解决了问题,非常感谢

Gre*_*ous 25

添加答案,因为评论救了我!

检查 go 解决方案中的所有文件是否都使用相同版本的 chi。如果您使用 VSCode,它可能会导入与您预期不同的版本。在我的代码中,我有一个文件

import(
  "github.com/go-chi/chi"
)
Run Code Online (Sandbox Code Playgroud)

而在另一个

import(
  "github.com/go-chi/chi/v5"
)
Run Code Online (Sandbox Code Playgroud)

这意味着当我调用中间件函数来提取 URLParams 时,上下文找不到值。

TL;DR 检查所有文件是否使用相同版本的 Chi!

  • 偶然发现了同样的错误,这个回答对我帮助很大!:) (2认同)