gpt4 book ai didi

go - 将 JSON 解码为接口(interface)值

转载 作者:数据小太阳 更新时间:2023-10-29 03:06:26 24 4
gpt4 key购买 nike

由于 encoding/json 需要一个非零接口(interface)来解码:我如何可靠地制作用户提供的指针类型的(完整)副本,将其存储在我的 User 接口(interface)中,以及然后 JSON 解码成那个临时的?

注意:这里的目标是“无人值守”——也就是说,从 Redis/BoltDB 中提取字节,解码为接口(interface)类型,然后检查 GetID() 方法接口(interface)定义返回一个非空字符串,带有请求中间件。

Playground :http://play.golang.org/p/rYODiNrfWw

package main

import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"os"

"time"
)

type session struct {
ID string
User User
Expires int64
}

type User interface {
GetID() string
}

type LocalUser struct {
ID string
Name string
Created time.Time
}

func (u *LocalUser) GetID() string {
return u.ID
}

type Auth struct {
key []byte
// We store an instance of userType here so we can unmarshal into it when
// deserializing from JSON (or other non-gob decoders) into *session.User.
// Attempting to unmarshal into a nil session.User would otherwise fail.
// We do this so we can unmarshal from our data-store per-request *without
// the package user having to do so manually* in the HTTP middleware. We can't
// rely on the user passing in an fresh instance of their User satisfying type.
userType User
}

func main() {
// auth is a pointer to avoid copying the struct per-request: although small
// here, it contains a 32-byte key, options fields, etc. outside of this example.
var auth = &Auth{key: []byte("abc")}
local := &LocalUser{"19313", "Matt", time.Now()}

b, _, _, err := auth.SetUser(local)
if err != nil {
log.Fatalf("SetUser: %v", err)
}

user, err := auth.GetUser(b)
if err != nil {
log.Fatalf("GetUser: %#v", err)
}

fmt.Fprintf(os.Stdout, "%v\n", user)

}

func (auth *Auth) SetUser(user User) (buf []byte, id string, expires int64, err error) {
sess := newSession(user)

// Shallow copy the user into our config. struct so we can copy and then unmarshal
// into it in our middleware without requiring the user to provide it themselves
// at the start of every request
auth.userType = user

b := bytes.NewBuffer(make([]byte, 0))
err = json.NewEncoder(b).Encode(sess)
if err != nil {
return nil, id, expires, err
}

return b.Bytes(), sess.ID, sess.Expires, err
}

func (auth *Auth) GetUser(b []byte) (User, error) {
sess := &session{}

// Another shallow copy, which means we're re-using the same auth.userType
// across requests (bad).
// Also note that we need to copy into it session.User so that encoding/json
// can unmarshal into its fields.
sess.User = auth.userType

err := json.NewDecoder(bytes.NewBuffer(b)).Decode(sess)
if err != nil {
return nil, err
}

return sess.User, err
}

func (auth *Auth) RequireAuth(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
// e.g. user, err := store.Get(r, auth.store, auth.userType)
// This would require us to have a fresh instance of userType to unmarshal into
// on each request.

// Alternative might be to have:
// func (auth *Auth) RequireAuth(userType User) func(h http.Handler) http.Handler
// e.g. called like http.Handle("/monitor", RequireAuth(&LocalUser{})(SomeHandler)
// ... which is clunky and using closures like that is uncommon/non-obvious.
}

return http.HandlerFunc(fn)
}

func newSession(u User) *session {
return &session{
ID: "12345",
User: u,
Expires: time.Now().Unix() + 3600,
}
}

最佳答案

如果您需要深拷贝一个接口(interface),请将该方法添加到您的接口(interface)中。

type User interface {
GetID() string
Copy() User
}

type LocalUser struct {
ID string
Name string
Created time.Time
}

// Copy receives a copy of LocalUser and returns a pointer to it.
func (u LocalUser) Copy() User {
return &u
}

关于go - 将 JSON 解码为接口(interface)值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35447480/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com