0

在 Go中,我试图interface{}从. 我确定这是一个已解决的问题,但我无法弄清楚。statement.Exec()go-sqlite3

基本上我有一个struct我想传递给一个函数的行数据,它将把它插入一个sqlite db。问题是我希望能够以编程方式控制 statement.Exec()函数中的内容

这是一段摘录:


type hostRows struct {
    domain   string
}

type clientRows struct {
    name   string
}

func main() {

    ...

    data := hostRows{domain: "dom.com"}
    insertRow(sqliteDatabase, data)

    data2 := clientRows{name: "bob"}
    insertRow(sqliteDatabase, data2)

    ...

}

func insertRow(db *sql.DB, row interface{}) {

    insertSQL := "INSERT INTO table(col) VALUES (?)"
    statement, _ := db.Prepare(insertSQL)
    
    statement.Exec(row) // here's the issue, how can I extract the element in the interface to pass it to the function for Exec to understand
    
}

我知道在这个示例中,我可以将行类型硬编码为 struct 和 type statement.Exec(row.(hostRows).domain),但现在代码将中断到传递客户端结构时。

这是Exec功能的减速

func (s *Stmt) Exec(args ...interface{}) (Result, error) 

我试过玩,reflect但到目前为止它对我没有用。我目前唯一的解决方案是使用switch可以检查并准备正确命令的条件Exec,但这并不狡猾。

type hostRows struct {
    domain   string
}

type clientRows struct {
    name   string
}

func main() {

    ...

    data := hostRows{domain: "dom.com"}
    insertRow(sqliteDatabase, 1, data)

    data2 := clientRows{name: "bob"}
    insertRow(sqliteDatabase, 2, data2)

    ...

}

func insertRow(db *sql.DB, i int, row interface{}) {

    insertSQL := "INSERT INTO table(col) VALUES (?)"
    statement, _ := db.Prepare(insertSQL)
    
    // This basically could be a working solution, but I'm sure there is a better one
    switch i {
        case 1:
            data := row.(hostRows)
            statement.Exec(data.domain)
        case 2:
            data := row.(clientRows)
            statement.Exec(data.name)
    }
    
}

编辑:更正了 INSERT 语句;忘记列。更正statement.Exec(row.domain)statement.Exec(row.(hostRows).domain) edit2:添加了第二个示例

4

1 回答 1

2

请记住,为了reflect.Interface()工作,您必须导出字段。要使用反射实现你想要的,你可以尝试这样的事情:

type hostRows struct {
    //Should export field to read it using reflect.Value.Interface()
    Domain string
}

type clientRows struct {
    //Should export field to read it using reflect.Value.Interface()
    Name string
}

func insertRow(db *sql.DB, i int, row interface{}) {
    rv := reflect.ValueOf(row)
    var args []interface{}
    for i := 0; i < rv.NumField(); i++ {
        args = append(args, rv.Field(i).Interface())
    }
    db.Exec("Insert Satement...", args...)
}
于 2021-03-04T21:51:56.203 回答