我在使用 go-jet 时遇到一个非常奇怪的问题,它似乎只能填充匿名结构而不是命名结构?
这是我的代码
package api
import (
"fmt"
"reflect"
"github.com/Napam/apato/internal/api/database"
// gen "github.com/Napam/apato/internal/generated"
. "github.com/Napam/apato/internal/generated/apato/app/table"
"github.com/Napam/apato/internal/utils/auth"
"github.com/Napam/apato/internal/utils/logging"
. "github.com/go-jet/jet/v2/postgres"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog"
)
func (h *Handlers) GetAuthUser(c echo.Context) error {
logger := logging.GetRequestLogger(c)
logger.Info().Msg("Start get auth user")
userId, err := auth.GetRequestUserId(c)
if err != nil {
return &echo.HTTPError{
Code: 401,
Message: "Unauthorized",
}
}
logger.Info().Str("userId", userId).Msg("Retrieved user id from request context")
selectStatment := Users.SELECT(
Users.FirstName.AS("firstName"),
Users.LastName.AS("lastName"),
Users.Email.AS("email"),
Users.ID.AS("id"),
Users.ProviderName.AS("providerName"),
).WHERE(
Users.ID.EQ(String(userId)),
)
logger.Debug().Func(func(e *zerolog.Event) {
e.Str("SQL", selectStatment.DebugSql())
}).Msg("SQL to get user")
type TEST struct {
Email string `json:"email"`
FirstName *string `json:"firstName,omitempty"`
Id string `json:"id"`
LastName *string `json:"lastName,omitempty"`
ProviderName *string `json:"providerName,omitempty"`
}
var DBUser = TEST{
Email: "",
FirstName: nil,
Id: "",
LastName: nil,
ProviderName: nil,
}
var DBUser2 struct {
Email string `json:"email"`
FirstName *string `json:"firstName,omitempty"`
Id string `json:"id"`
LastName *string `json:"lastName,omitempty"`
ProviderName *string `json:"providerName,omitempty"`
}
// Use reflection to inspect the fields of DBUser
val := reflect.ValueOf(DBUser)
for i := 0; i < val.NumField(); i++ {
field := val.Type().Field(i)
value := val.Field(i).Interface()
logger.Debug().Str("Field", field.Name).Interface("Value", value).Interface("Tag", field.Tag).Msg("DBUser field value")
}
// Use reflection to inspect the fields of DBUser2
val = reflect.ValueOf(DBUser2)
for i := 0; i < val.NumField(); i++ {
field := val.Type().Field(i)
value := val.Field(i).Interface()
logger.Debug().Str("Field", field.Name).Interface("Value", value).Interface("Tag", field.Tag).Msg("DBUser2 field value")
}
err = selectStatment.Query(database.DB, &DBUser)
if err != nil {
return fmt.Errorf("Error querying database: %w", err)
}
err = selectStatment.Query(database.DB, &DBUser2)
if err != nil {
return fmt.Errorf("Error querying database: %w", err)
}
logger.Debug().Interface("DBUser", DBUser).Msg("Retrieved user from database")
logger.Debug().Interface("DBUser2", DBUser2).Msg("Retrieved user from database")
return c.JSON(200, map[string]any{
"DBUser": DBUser,
"DBUser2": DBUser2,
})
}
有人会认为这里的输出是两个相同的对象,但实际上输出是:
{
DBUser: { email: '', id: '' },
DBUser2: {
email: '[email protected]',
firstName: 'Naphat',
id: '123123123',
lastName: 'Amundsen',
providerName: 'google'
}
}
go-jet 的文档指出:“查询使用反射来内省目标类型结构和结果集列名称(别名),为结果集列找到适当的目标字段”
所以我使用反射仔细检查了结构,它们看起来相同:
2024-09-14T17:43:25+02:00 [DEBUG] DBUser field value Field=Email Tag="json:\"email\"" Value= requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser field value Field=FirstName Tag="json:\"firstName,omitempty\"" Value=null requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser field value Field=Id Tag="json:\"id\"" Value= requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser field value Field=LastName Tag="json:\"lastName,omitempty\"" Value=null requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser field value Field=ProviderName Tag="json:\"providerName,omitempty\"" Value=null requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser2 field value Field=Email Tag="json:\"email\"" Value= requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser2 field value Field=FirstName Tag="json:\"firstName,omitempty\"" Value=null requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser2 field value Field=Id Tag="json:\"id\"" Value= requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser2 field value Field=LastName Tag="json:\"lastName,omitempty\"" Value=null requestId=1726328605558-tVF-
2024-09-14T17:43:25+02:00 [DEBUG] DBUser2 field value Field=ProviderName Tag="json:\"providerName,omitempty\"" Value=null requestId=1726328605558-tVF-
如果我将 DBUser 设置为匿名结构,则一切正常
这可能是什么原因造成的? go-jets 文档中有具体的例子,作者使用命名结构就很好。
环境信息:
这真是令人尴尬;所以这实际上包含在 go-jet 的常见问题解答中:https://github.com/go-jet/jet/wiki/FAQ#scan-stopped-working-after-naming-a-destination-type
基本上,必须“定位”SQL 名称中的结构名称,也就是说,在我的事业中我必须这样做
selectStatment := Users.SELECT(
Users.FirstName.AS("test.firstName"),
Users.LastName.AS("test.lastName"),
Users.Email.AS("test.email"),
Users.ID.AS("test.id"),
Users.ProviderName.AS("test.providerName"),
).WHERE(
Users.ID.EQ(String(userId)),
)