Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何在sql扫描函数中传递对结构属性的引用列表以自动化该过程?_Go - Fatal编程技术网

Go 如何在sql扫描函数中传递对结构属性的引用列表以自动化该过程?

Go 如何在sql扫描函数中传递对结构属性的引用列表以自动化该过程?,go,Go,我有一个这种形式的结构,我也添加了方法 type User struct { Id int64 Email string Username string GeonameId int64 Birthdate string Hash string ActiveImage string About string Verified bool

我有一个这种形式的结构,我也添加了方法

type User struct {
    Id           int64
    Email        string
    Username     string
    GeonameId    int64
    Birthdate    string
    Hash         string
    ActiveImage  string
    About        string
    Verified     bool
    Notification bool
    Joined       int64
    LastActivity int64
    Ipv4         int64
    Deleted      bool
}
但是每次我进行查询时,我都会手动将查询的结果分配给这些属性,而这些属性并不是很枯燥。每次我在数据库中添加一个新列时,我都必须手动更改大量代码行,这不是很理想

我采用的方法有:

func ByEmail(email string) (*User, error) {

    query := `
        SELECT *
        FROM user
        WHERE
            email = ? AND
            deleted = 0
        LIMIT 1;
    `

    user := &User{}
    err := sql.DB.QueryRow(query, email).Scan(
        &user.Id,
        &user.Email,
        &user.Username,
        &user.GeonameId,
        &user.Birthdate,
        &user.Hash,
        &user.ActiveImage,
        &user.About,
        &user.Verified,
        &user.Notification,
        &user.Joined,
        &user.LastActivity,
        &user.Ipv4,
        &user.Deleted,
    )
    if err != nil {
        return nil, err
    }

    return user, nil
}
在数据库中创建新行时:

func (u *User) Create() error {

    if u.Id != 0 {
        return fmt.Errorf("User.Create: Struct already has an Id.")
    }

    query := `
        INSERT INTO user
        SET
            email = ?,
            username = ?,
            geonameid = ?,
            birthdate = ?,
            hash = ?,
            active_image = ?,
            about = ?,
            verified = ?,
            notification = ?,           
            joined = ?,
            lastactivity = ?,
            ipv4 = ?,
            deleted = ?;
    `

    stmt, err := sql.DB.Prepare(query)
    if err != nil {
        return err
    }

    res, err := stmt.Exec(
        u.Email,
        u.Username,
        u.GeonameId,
        u.Birthdate,
        u.Hash,
        u.ActiveImage,
        u.About,
        u.Verified,
        u.Notification,
        u.Joined,
        u.LastActivity,
        u.Ipv4,
        u.Deleted,
    )
    if err != nil {
        return err
    }

    lastId, err := res.LastInsertId()
    if err != nil {
        return err
    }

    u.Id = lastId

    return nil
}
我已经看了一些反射用法的例子,但是我仍然没有完全理解它。我不知道如何用一种简单的方式来做

如何通过在下面的Scan和Exec函数中发送对struct属性或类似内容的引用片段来自动化此过程

编辑:

我尝试通过以下操作获取对结构属性的引用:

user, _ := user.ById(1)
val := reflect.ValueOf(user).Elem()

fmt.Println(&user.Id)
fmt.Println(val.Field(0).Pointer())
但它惊慌失措,给了我这个错误:

panic: reflect: call of reflect.Value.Pointer on int64 Value

我的建议是,使用ORM包

关于您的恐慌,请参考golang:

如果v的种类不是Chan、Func、Map、Ptr、Slice或UnsafePointer,它就会恐慌

下面是一个使用反射的属性复制器示例

func CopyField(dst interface{}, src interface{}) {
dstVal := reflect.ValueOf(dst).Elem()
srcVal := reflect.ValueOf(src).Elem()

for i := 0; i < srcVal.NumField(); i++ {
    n := srcVal.Type().Field(i).Name
    dstField := dstVal.FieldByName(n)
    if dstField.IsValid() {
        dstField.Set(srcVal.Field(i))
    }
}
你看过吗?我也用我自己的自定义方式编写了reflect,但最终只使用sqlx更有意义。你的恐慌是有意义的:reflect包有点元,需要大量的实践才能有效地使用。