我已设法使用本地上下文通过自定义中间件设置数据库查询结果。我试图了解如何对用户进行身份验证,然后从数据库中提取其详细信息并将其注入上下文中。这已经完成了。
路由上最后一个方法的本地数据实际上是一个接口,我想从之前的身份验证中间件设置的数据中提取字段。如何将此接口类型处理为某种形式(如结构或 json),以便获取用于执行某些逻辑的字段和值?
user := c.Locals("user")
fmt.Println("checking for locals",user)
Run Code Online (Sandbox Code Playgroud)
从上面的用户是struct user
{
Name string `json:"name"`
Emain string `json:"email"`
ID string `json:"id"`
Password string `json:"password"`
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能得到姓名和电子邮件?
我想为每个子主路线制作单独的文件。我正在使用 go 1.17
main.go
package main
import (
"rolling_glory_go/routes"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
err := c.SendString("Hello golang!")
return err
})
routes.R_login(app.Group("/login"))
routes.R_users(app.Group("/users"))
app.Listen(":3000")
}
Run Code Online (Sandbox Code Playgroud)
我想从中导入路由r_login.go
,r_users.go
这样我就可以管理来自不同文件的许多路由,而不是将单个文件中的许多路由放入main.go
. 我遇到这样的错误。
.\main.go:17:26: cannot use app.Group("/login") (type fiber.Router) as type *fiber.Group in argument to routes.R_login: need type assertion
.\main.go:18:26: cannot use app.Group("/users") (type fiber.Router) as type *fiber.Group in argument to routes.R_users: need type assertion
Run Code Online (Sandbox Code Playgroud)
我的结构文件夹
r_login.go
package routes
import "github.com/gofiber/fiber/v2"
func …
Run Code Online (Sandbox Code Playgroud) 我正式向 Stack Overflow 上的仁慈的撒玛利亚人喊一声叔叔。
我正在尝试使用模拟数据库对我的 GORM (Postgres) + Fiber API 进行单元测试。我有一个Card
模型和一个CreateCardReqBody
POST 请求正文的模型。为了设置测试,我创建一个随机CreateCardReqBody
实例,将其编组为 JSON,然后将其传递到*httptest.Request
. 处理程序使用 Fiber 的(*fiber.Ctx).BodyParser
函数将请求主体“解组”为空Card
结构。但是,当我运行应该通过的测试时,Fiber 抛出“无法处理的实体”错误。
以下是我的代码的相关部分;测试文件是本教程和Fiber 关于 (*App).Test 方法的文档的组合。(我意识到代码可以清理;我只是想获得生命的证明,然后专注于修改:)
我做了一些事情来调试这个:我使用与测试相同的值发出了 Postman POST 请求,并且它有效。在测试本身中,我对CreateCardReqBody
结构进行编组然后解组,这样就可以了。我已经三次检查了 JSON 字段的拼写是否匹配、结构字段是否已导出等。我还运行了 VSCode 调试器,body
Fiber.Ctx 中的字段对我来说看起来也是正确的。
我开始怀疑这是否与 Fiber 从测试请求和真实请求中解析正文的方式有关。我将非常感谢任何人能分享对此的见解!
模型定义
type Card struct {
gorm.Model
// Implicit Gorm foreign key to fleet ID
FleetID uint `gorm:"index" json:"fleet_id" validate:"required,min=1"`
// Card provider's account number
ProviderAccountNumber string `json:"provider_account_number"` …
Run Code Online (Sandbox Code Playgroud) 原始问题
Update
在 GORM 中使用该方法时,不会保存新数据。即我想设置一个bool
from true
to false
,但即使在Update
方法之后它仍然保持真实。
在该方法的描述中有一个警告:“使用结构更新时警告,GORM 不会更新具有零值的字段”
由于我使用结构来更新并且false
是 的零值bool
,这似乎是预期的行为,但我看不出有任何理由这样做以及如何克服这一点。
func UpdateData(c *fiber.Ctx) error {
db := database.DBConn
data := new([]entities.Data)
if err := c.BodyParser(&data); err != nil {
return err
}
db.Update(&data)
return c.JSON(data)
}
Run Code Online (Sandbox Code Playgroud)
解决方案总结
首先,正如建议的那样,我new
在实例化结构时省略了关键字。然后,我使用了一个辅助函数(来自此处)将结构转换为映射,同时将 json 别名保留为键:
// StructToMap Converts a struct to a map while maintaining the json alias as keys
func StructToMap(obj interface{}) (newMap map[string]interface{}, err error) {
data, err …
Run Code Online (Sandbox Code Playgroud) 我有一个SSE
端点将数据发送到前端,并且该数据是从另一个API
端点检索的。channels
我对in还很陌生go
,似乎我必须触发 API 端点两次,以便 SSE 端点将数据发送到前端一次。就目前而言,我还没有编写前端代码来建立 SSE 连接,因为我仍在使用通道。有人可以解释为什么这需要调用 API 两次才能让 SSE 发送数据吗?
上交所路线
func SendSSE(appCtx *fiber.Ctx, dataChannel chan string) error {
appCtx.Set("Content-Type", "text/event-stream")
appCtx.Set("Cache-Control", "no-cache")
appCtx.Set("Connection", "keep-alive")
appCtx.Set("Transfer-Encoding", "chunked")
appCtx.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
log.Println("SSE Opened")
for {
log.Println("Retrieving data channel..")
fmt.Fprintf(w, "data: Message: %s\n\n", <-dataChannel)
log.Println(<-dataChannel)
err := w.Flush()
if err != nil {
// Refreshing page in web browser will establish a new
// SSE connection, but only (the last) one is alive, …
Run Code Online (Sandbox Code Playgroud)