背景
上一章
Go语言开发基于SQLite数据库实现用户表新增接口(二)
这一章我们实现用户表的查询详情接口
代码实现
mapper层
type UserMapper interface {
GetById(id uint64) (*model.User, error)
}
type userMapper struct {
}
func (m *userMapper) GetById(id uint64) (*model.User, error) {
// 创建 model.User 的指针实例
user := &model.User{}
result, err := model.GetById(user.TableName(), id, user)
if err != nil {
return nil, err
}
// 确保返回的结果是 *model.User 类型
user, ok := result.(*model.User)
if !ok {
return nil, fmt.Errorf("expected *model.User, but got %T", result)
}
return user, nil
}
ModelTable实现
func GetById(tableName string, id uint64, dest interface{}) (interface{}, error) {
// 确保 dest 是指针类型
val := reflect.ValueOf(dest)
if val.Kind() != reflect.Ptr || val.IsNil() {
return nil, fmt.Errorf("dest must be a non-nil pointer")
}
// 构造 SQL 查询
query := fmt.Sprintf("SELECT * FROM %s WHERE id = ? LIMIT 1", tableName)
// 执行查询
row := config.Db.QueryRow(query, id)
// 获取结构体的字段
fieldPointers, err := getFieldPointers(reflect.TypeOf(dest).Elem(), reflect.ValueOf(dest).Elem())
if err != nil {
return nil, err
}
// 使用 Scan 将查询结果映射到结构体
err = row.Scan(fieldPointers...)
if err != nil {
if err == sql.ErrNoRows {
return nil, fmt.Errorf("No rows found with id %d", id)
}
return nil, err
}
return dest, nil
}
// 递归地获取结构体字段的指针(支持嵌套结构体)
func getFieldPointers(t reflect.Type, v reflect.Value) ([]interface{}, error) {
var fieldPointers []interface{}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fieldValue := v.Field(i)
// 如果字段是结构体类型,递归进入
if fieldValue.Kind() == reflect.Struct {
// 递归处理嵌套的结构体字段
nestedPointers, err := getFieldPointers(field.Type, fieldValue)
if err != nil {
return nil, err
}
fieldPointers = append(fieldPointers, nestedPointers...)
} else {
// 否则将字段的指针添加到字段指针数组
fieldPointers = append(fieldPointers, fieldValue.Addr().Interface())
}
}
return fieldPointers, nil
}
这里我们映射的结构体中的对应db字段 , 这样的好处是我们这个方法是基础方法,其他结构体中只要有ModelTable结构体,我们就可以直接继续使用了。
service层
type UserService interface {
GetById(id uint64) (*model.User, error)
}
service实现层
type UserServiceImpl struct {
m mapper.UserMapper
}
func (u UserServiceImpl) GetById(id uint64) (*model.User, error) {
return u.m.GetById(id)
}
controller层
type UserController struct {
UserService service.UserService
}
func (u *UserController) GetById(rc *req.Ctx) {
id := uint64(req.PathParamInt(rc.GinCtx, "id"))
user, err := u.UserService.GetById(id)
assert.IsNil(err)
rc.ResData = user
}
这里有个PathParamInt方法 获取路径上面的参数
func PathParamInt(g *gin.Context, pm string) int {
value, _ := strconv.Atoi(g.Param(pm))
return value
}
接口
测试
源码地址
使用Go语言开发基于SQLite数据库实现用户表相关接口项目示例,可进行扩展,拿来即用
参考
代码风格参考的mayfly-go ,SQLite这块是自己实现的