2023-11-07

create map with types that implement interface

How to create a map with struct types that implements interface

I'm trying to create a map that stores the type for each column (database)

There is a few things wrong with the code. I don't really know how to solve it

Type_string and Type_int implements sql.Scanner with method Scan

I want to be able to fetch a non-predefined set of fields from a database. I don't know if this is the right approach?

Want a less strict version than just passing a predifined struct to rows.Scan()

Prefer a solution without reflect if possible

Types

type Type_string string

func (t *Type_string) Scan(value any) error {
    switch value := value.(type) {
    case []uint8:
        *t = Type_string(value)
    default:
        return fmt.Errorf("Invalid database type: %T %v", value, value)
    }
    return nil
}

type Type_int int

func (t *Type_int) Scan(value any) error {
    switch value := value.(type) {
    case int64:
        *t = Type_int(value)
    default:
        return fmt.Errorf("Invalid database type: %T %v", value, value)
    }
    return nil
}

Define table data types

type table_field struct {
    value_type  sql.Scanner
}

table_type := map[string]table_field{
    "id": table_field{
        value_type: Type_int{},
    },
    "name": table_field{
        value_type: Type_string{},
    },
}

Fetch from database

// Build pointer to pass to `rows.Scan()`
ptr     := make([]any, len(cols))
for i, name := range cols {
    ptr[i] = &table_type[name].value_type
}

if err := rows.Scan(ptr...); err != nil {
    fmt.Println("err:", err)
}

Error

invalid composite literal type Type_int
invalid composite literal type Type_string
invalid operation: cannot take address of table_type[name].value_type (value of type sql.Scanner)


No comments:

Post a Comment