类型检查,不需要硬编码类型或在数组中存储类型信息



我想知道go是否提供了一个选项来避免在没有反射或运行时类型检查的情况下在交换机分支中硬编码类型。

这里的GetGeneric不应该知道它接收的类型。调用者告诉GetGeneric使用类型X, GetGeneric通过支撑。获取填充模型数据。

在stmt。Get要求&具体类型的:属于具体类型的这里有一个小例子。但我真的不喜欢我需要一个硬密码类型为每个模型作为一个单独的案例分支,它违背了整个目的,并且我被限制在一个stmt的接口上。得到提供。

func (pdb *PersistentDb) GetGeneric(ctx context.Context, sqlStmt string,
model interface{}, args ...interface{}) (interface{}, error) {
if pdb == nil {
return nil, fmt.Errorf("you need to initilize persistent db first")
}
db, err := pdb.connectx(ctx)
if err != nil {
callistolog.Errorf("Failed connect to database error: %v", err)
return nil, err
}
defer db.Close()
stmt, errPrepare := db.Preparex(sqlStmt)
if errPrepare != nil {
callistolog.Errorf("Failed prepare sql statement error: %v", errPrepare)
return nil, errPrepare
}
defer stmt.Close()
switch t := model.(type) {
case models.Role:
err = stmt.Get(&t, args...)
return t, err
case models.Tenants:
err = stmt.Get(&t, args...)
return t, err
// here for each models.Type I need add branch
default:
callistolog.Errorf("got unknown type")
}
return model, fmt.Errorf("unknown type")
}

一个选项是通过反射进行运行时检查,但我在想我可以以某种方式声明数组/切片类型和优化开关分支到if分支,并在循环中迭代。

类似于(伪代码)

如果在模型数组中键入T。把T作为泛型,使它成为具体类型T_hat将t_that地址传递给stmt。得到

在某些语言中,您可以拥有Object[]等的数组您还可以检查对象类型。

在这个例子中,调用者提供了一个模型作为通用接口在GetGeneric模型内部,根据该类型是否在已知类型的数组中以及它是否成为具体类型这一事实,对具体类型进行类型检查。Get接受。

例如,

如何在slice中存储类型信息而不是值,然后分派到stmt.Get(及t, args…)

types := []interface{} {model, model1, model2}
for _,v := range types {
}

谢谢

假设您正在使用sqlx,添加另一层反射只是没有意义,而是按照设计的使用方式使用它。

func (pdb *PersistentDb) GetGeneric(ctx context.Context, sqlStmt string, model interface{}, args ...interface{}) error {
if pdb == nil {
return fmt.Errorf("you need to initilize persistent db first")
}
db, err := pdb.connectx(ctx)
if err != nil {
callistolog.Errorf("Failed connect to database error: %v", err)
return err
}
defer db.Close()
stmt, errPrepare := db.Preparex(sqlStmt)
if errPrepare != nil {
callistolog.Errorf("Failed prepare sql statement error: %v", errPrepare)
return errPrepare
}
defer stmt.Close()
if err := stmt.Get(model, args...)
callistolog.Error(err)
return err
}
return nil
}
role := models.Role{}
if err := pdb.GetGeneric(ctx, "select ...", &role, args...); err != nil {
return err
}
fmt.Println(role)
// ...
tentants := models.Tenants{}
if err := pdb.GetGeneric(ctx, "select ...", &tenants, args...); err != nil {
return err
}
fmt.Println(tentants)

请注意,如果您不打算重用语句,则无需手动准备语句。

最新更新