Q:

How to Unmarshal float64 records in database to create insert

The project I'm working on is supposed to read a file, then generate inserts based on that file.
Right now, the script works (Kind of).
I'm running into an issue when creating the structs for the tables, specifically for fields are float64's.
The script I've made accounts for fields that are type string, and int. I'm able to insert into tables that have those field types, but if there's a field in my database which is a float, the script doesn't insert any of the data.
Here's how my script is currently set-up to check for types of int and string.
func UnmarshalCsvRecord(readerTest *csv.Reader, v interface{}) error {
    recordtest, err := readerTest.Read()
    if err != nil {
        return err
    }
    s := reflect.ValueOf(v).Elem()
    if s.NumField() != len(recordtest) {
        return &CheckField{s.NumField(), len(recordtest)}
    }
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        switch f.Type().String() {
        case "string":
            f.SetString(recordtest[i])
        case "int":
            ival, err := strconv.ParseInt(recordtest[i], 10, 0)
            if err != nil {
                return err
            }
            f.SetInt(ival)
        default:
            return &UnsupportedCheck{f.Type().String()}
        }
    }
    return nil
}

type CheckField struct {
    expected, found int
}

func (e *CheckField) Error() string {
    return "CSV line fields mismatch. Expected " + strconv.Itoa(e.expected) + " found " + strconv.Itoa(e.found)
}

type UnsupportedCheck struct {
    TypeCheck string
}

func (e *UnsupportedCheck) Error() string {
    return "Unsupported type: " + e.TypeCheck
}

What can I do to account for float64 fields in my struct?
type ClientSalesTable struct {
    ID int `csv:"id"`
    Amount float64 `csv:"amount"`
    ClientName string `csv:"clientName"`
}

A:

Handle floats using the same pattern as integers. Replace strconv.ParseInt with strconv.ParseFloat. Replace f.SetInt(ival) with f.SetFloat(fval). 
Bonus fix: Switch on f.Type().Kind() instead of the string.
func UnmarshalCsvRecord(readerTest *csv.Reader, v interface{}) error {
    recordtest, err := readerTest.Read()
    if err != nil {
        return err
    }
    s := reflect.ValueOf(v).Elem()
    if s.NumField() != len(recordtest) {
        return &CheckField{s.NumField(), len(recordtest)}
    }
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        switch f.Type().Kind() {
        case reflect.String:
            f.SetString(recordtest[i])
        case reflect.Int:
            ival, err := strconv.ParseInt(recordtest[i], 10, f.Type().Bits())
            if err != nil {
                return err
            }
            f.SetInt(ival)
        case reflect.Float64:
            fval, err := strconv.ParseFloat(recordtest[i], f.Type().Bits())
            if err != nil {
                return err
            }
            f.SetFloat(fval)
        default:
            return &UnsupportedCheck{f.Type().String()}
        }
    }
    return nil
}

By adding more cases, the code above can be extend to handle all integer and float types:
switch f.Type().Kind() {
...
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
...
case reflect.Float64, reflect.Float32:
...
}

