如何使用"输入struct"保存在控制器中访问的中间件的上下文中

时间:2018-02-02 06:29:43

标签: go struct

这是关于GoLang的第一个问题请温柔。 我正在构建一个测试JSON API。

我有类型结构,名为用户

type User struct {
    UserID              int
    Email               string
    FirstName           string
    LastName            string
    PasswordHash        string
}

在中间件中,我验证 JWT令牌是否有效,如果有效,我会加载用户的整个记录​​并将其保存在上下文中,以便在下面的处理程序中可用。

所以在中间件中,我像这样保存User struct

    context.Set(r, "User",  *User)
    fmt.Println(*User)

    next.ServeHTTP(w, r)

Println 的输出

{12 sallu@domain.com.au Mr. Sallu $2a$14oUg3d1rm./.B/vUyhYR9/hlHfagE4tGicNc14EWK3u }

然后在最终处理程序中,我访问此上下文并获取User对象。

User    := context.Get(r, "User")

fmt.Println("---User---", fmt.Sprintf(" %T ", User))
fmt.Println(User)

Println 的输出

---User---  models.User
{12 sallu@domain.com.au Mr. Sallu $2a$14oUg3d1rm./.B/vUyhYR9/hlHfagE4tGicNc14EWK3u }

问题是,当我访问 User.Email 时,我在控制器中收到错误

User.Email undefined (type interface {} is interface with no methods)

我该如何解决这个问题? 我想使用User.Email或User.UserID。 似乎上下文正在做些什么。

请帮忙

2 个答案:

答案 0 :(得分:5)

代码中的任何地方请为变量和类型使用不同的名称。

e.g。保持类型User和变量user

在您的控制器中,键入断言您的user返回User

if u, ok := user.(User); ok {
    fmt.Println(u.Email)
}

https://tour.golang.org/methods/15

答案 1 :(得分:0)

User.Email在那里有点含糊不清。您对类型定义和变量使用相同的名称User。但是,您看到的错误消息:

User.Email undefined (type interface {} is interface with no methods)

表明编译器理解User是变量,因为它认为类型是interface{} - Go中的泛型类型。

如果我根本不使用变量,那么你看到的错误消息与我得到的错误消息略有不同,但只是尝试访问类型上不存在的方法,例如:

package main

import(
    "fmt"
)

type User struct {
    Email           string
}

func main() {
    fmt.Println(User.Email)
}

执行时会输出以下错误:

User.Email undefined (type User has no method Email)

但是,最好将变量名称更改为与类型名称不同,例如

u := context.Get(r, "User")

然后您将访问u.Email

鉴于编译器将您的变量视为类型interface{}而不是类型User,biosckon可能是正确的,您在从上下文中提取后缺少类型断言。请参阅the go blog on context,尤其是:

  

FromContext从Context:

中提取userIP
func FromContext(ctx context.Context) (net.IP, bool) {
    // ctx.Value returns nil if ctx has no value for the key;
    // the net.IP type assertion returns ok=false for nil.
    userIP, ok := ctx.Value(userIPKey).(net.IP)
    return userIP, ok
}

另见this Stackoverflow question and answer on fetching values from context,尤其是:

  

您还需要使用正确的类型设置和提取值...我经常定义辅助函数来提取上下文值并执行类型断言

这有什么奇怪的是你的打印语句的输出,使它看起来像你有正确的类型。但是,由于您对变量和类型使用相同的名称,因此有点模棱两可。并且 - 它看起来并不像你共享所有代码 - 是那些来自你首先设置它们的范围的打印而不是从不同范围的上下文中提取的打印?如果是这样,那将解释其中的差异。