Ответ 1
Сделайте это так:
var err *os.Error
t := reflect.TypeOf(err).Elem()
Или в одной строке:
t := reflect.TypeOf((*os.Error)(nil)).Elem()
Чтобы определить, реализует ли данный тип интерфейса интерфейс с использованием пакета отражения, вам необходимо передать рефлексию. Тип для отражения. Type.Implements(). Как вы получаете один из этих типов?
В качестве примера, попытка получить тип неинициализированного типа os.Error(interface) работает не (он паникует, когда вы вызываете на нем Kind())
var err os.Error
fmt.Printf("%#v\n", reflect.TypeOf(err).Kind())
Сделайте это так:
var err *os.Error
t := reflect.TypeOf(err).Elem()
Или в одной строке:
t := reflect.TypeOf((*os.Error)(nil)).Elem()
Даже реакция Shaws правильная, но краткая. Еще несколько деталей из документации метода reflect.TypeOf:
// As interface types are only used for static typing, a
// common idiom to find the reflection Type for an interface
// type Foo is to use a *Foo value.
writerType := reflect.TypeOf((*io.Writer)(nil)).Elem()
fileType := reflect.TypeOf((*os.File)(nil))
fmt.Println(fileType.Implements(writerType))
Для гуглеров я просто столкнулся с ужасной ошибкой scannable dest type interface {} with >1 columns (XX) in result
.
Ответ Эвана Шоу не помог мне. Вот как я это решил. Я также использую библиотеку lann/squirrel
, но вы можете легко принять это.
Решение действительно не так сложно, просто зная магическую комбинацию отражать звонки, чтобы сделать.
Функция me.GetSqlx()
просто возвращает экземпляр в *sqlx.DB
func (me *CommonRepo) Get(query sq.SelectBuilder, dest interface{}) error {
sqlst, args, err := query.ToSql()
if err != nil {
return err
}
// Do some reflection magic so that Sqlx doesn't hork on interface{}
v := reflect.ValueOf(dest)
return me.GetSqlx().Get(v.Interface(), sqlst, args...)
}
func (me *CommonRepo) Select(query sq.SelectBuilder, dest interface{}) error {
sqlst, args, err := query.ToSql()
if err != nil {
return err
}
// Do some reflection magic so that Sqlx doesn't hork on interface{}
v := reflect.ValueOf(dest)
return me.GetSqlx().Select(v.Interface(), sqlst, args...)
}
Затем, чтобы вызвать его, вы можете:
func (me *myCustomerRepo) Get(query sq.SelectBuilder) (rec Customer, err error) {
err = me.CommonRepo.Get(query, &rec)
return
}
func (me *myCustomerRepo) Select(query sq.SelectBuilder) (recs []Customer, err error) {
err = me.CommonRepo.Select(query, &recs)
return
}
Это позволяет вам иметь сильные типы на всем протяжении, но имеет общую логику в одном месте (CommonRepo
в этом примере).