Is it possible to go in go type structure as a parameter of a function / method? For example:

type MyEntity struct {} type MyEntity2 struct {} func goProc(t type) { b := make(t) } func TestEncription(test *testing.T) { goProc(MyEntity.type) goProc(MyEntity2.type) } 

Pishu banding from db. If one entry is ok:

 type DbEntity interface { bindEntity(rows *pgx.Rows, descriptionSlice []pgx.FieldDescription, colsCount *int) 

}

 func (customerEntity *CustomerEntity) bindEntity(rows *pgx.Rows, descriptionSlice []pgx.FieldDescription, colsCount *int) { val, _ := rows.Values() for i := 0; i < *colsCount; i++ { switch descriptionSlice[i].Name { case "customer_id": customerEntity.CustomerId = val[i].(int64) case "account_name": customerEntity.AccountName = val[i].(string) case "customer_name": customerEntity.CustomerName = val[i].(string) } } 

}

But if the sheet (slice) objects the problem

 func queryForList(rows *pgx.Rows) []interface{} { defer rows.Close() descriptionSlice := rows.FieldDescriptions() colsCount := len(descriptionSlice) var entitySlice []interface{} for rows.Next() { //entity := CustomerEntity{} //entitySlice = append(entitySlice, bindEntityFunc(rows, descriptionSlice, &colsCount)) } return entitySlice 

}

queryForList - for all types of entities. And he doesn’t know anything about types

  • What for? Most likely, you can convert this design into an interface and its implementation. - D-side
  • The interface solves the problem if one record. I want to write a binding from db. - TomX01
  • At the moment I see the solution is to create a function: NewCustomer, NewAccount, etc. and pass to queryForList. Without generic krivinko, but will work. - TomX01

2 answers 2

Here, I thought up without reflect. But with a type switch inside, it's so much better if you have all types known at compile time.

https://play.golang.org/p/enekbRdLM4

 package main import ( "fmt" ) type CustomerEntity struct { Name string Meta struct { Desc string Properties map[string]string Users []string } } func NewCustomerEntity() *CustomerEntity { return &CustomerEntity{ Name: "hello" } } func queryForList(t interface{}) []interface{} { var entitySlice []interface{} var entity interface{} for i:=0; i< 1; i++ { switch t.(type) { case *CustomerEntity: entity = NewCustomerEntity() default: } entitySlice = append(entitySlice, entity) } return entitySlice } func main() { lst := queryForList((*CustomerEntity)(nil)) fmt.Printf("%#v", lst[0]) } 
  • Thank you, great solution! - TomX01

You have to use reflect, and it is slow. And you still torment with him =)

 package main import ( "fmt" "reflect" ) type CustomerEntity struct { Name string Meta struct { Desc string Properties map[string]string Users []string } } func queryForList(t reflect.Type) []interface{} { var entitySlice []interface{} for i:=0; i< 1; i++ { entity := reflect.New(t.Elem()) initializeStruct(t.Elem(), entity.Elem()) f := entity.Elem().FieldByName("Name") f.Set(reflect.ValueOf("hello")) entitySlice = append(entitySlice, entity.Interface()) } return entitySlice } func initializeStruct(t reflect.Type, v reflect.Value) { for i := 0; i < v.NumField(); i++ { f := v.Field(i) ft := t.Field(i) switch ft.Type.Kind() { case reflect.Map: f.Set(reflect.MakeMap(ft.Type)) case reflect.Slice: f.Set(reflect.MakeSlice(ft.Type, 0, 0)) case reflect.Chan: f.Set(reflect.MakeChan(ft.Type, 0)) case reflect.Struct: initializeStruct(ft.Type, f) case reflect.Ptr: fv := reflect.New(ft.Type.Elem()) initializeStruct(ft.Type.Elem(), fv.Elem()) f.Set(fv) default: } } } func main() { // Рекомендуется передавать именно пустой указатель, что бы не занимать память lst := queryForList(reflect.TypeOf((*CustomerEntity)(nil))) entity := lst[0].(*CustomerEntity) fmt.Printf("%#v\n", entity) // либо, если не знаешь к какому типу приводить val := reflect.ValueOf(lst[0]) fmt.Println(val.Elem().FieldByName("Name")) } 

Through reflect in the structure, you can fill in only exported fields.

You can try to rewrite to lst := queryForList((*CustomerEntity)(nil)) with the interface {} parameter, but I quickly failed and I scored =)

Suffer for health