Get client information with GET request in GO API For an API I have defined a &quot;Client&quot; struct which contains all the fields the client has in the database. When a GET request is made with the client ID the whole struct(The struct contains about 60 fields of different types) is returned with all available data. The request can be customized with a querystring &quot;fields&quot; which allow the user to return specific &quot;Client&quot; fields only regardless if they are empty, so omitempty or &quot;-&quot; will not work for my usecase.
GO playground example: https://play.golang.org/p/NTGxGQFz7-Y
type Client struct {
   Firstname   string `json:&quot;firstname&quot;`
   AltAddress  string `json:&quot;alt_address&quot;`
   Lastname    string `json:&quot;lastname&quot;`
}

Example: GET
GET /clients/id/1
Response:
{ 
  &quot;firstname&quot;:   &quot;Michael&quot;,
  &quot;alt_address&quot;: &quot;&quot;,
  &quot;lastname&quot;:    &quot;Smith&quot;
}

Example: GET with querystring
Get /clients/id/1?fields=firstname, alt_address
Response:
{ 
  &quot;firstname&quot;:   &quot;Michael&quot;,
  &quot;alt_address&quot;: &quot;&quot;
}

I have this method(objectToFilteredMap) which converts an interface(struct for example) to a map, removes the fields that are NOT defined in &quot;fieldNames&quot; and outputs it as a json object. But I feel like I am using to many &quot;for&quot; loops. Is there a more efficient way to filter out the unneeded fields? Or any other improvements would be appreciated.
var (
    regex = regexp.MustCompile(`^\w+$`)
)

func inSlice(slice []string, val string) bool {
    for _, item := range slice {
        if item == val {
            return true
        }
    }
    return false
}

func toMap(obj interface{}, fieldNames []string) (map[string]interface{}, error) {
    for k, f := range fieldNames {
        f = strings.TrimSpace(f)
        if !regex.Match([]byte(f)) {
            return nil, fmt.Errorf(&quot;Invalid field name: `%s`&quot;, f)
        }
        fieldNames[k] = strings.ToLower(f)
    }

    j, err := json.Marshal(obj)
    if err != nil {
        return nil, err
    }

    objMap := map[string]interface{}{}
    err = json.Unmarshal(j, &amp;objMap)
    if err != nil {
        return nil, err
    }

    for k := range objMap {
        if !inSlice(fieldNames, k) {
            delete(objMap, k)
        }
    }

    if len(objMap) == 0 {
        return nil, fmt.Errorf(&quot;field(s) not found&quot;)
    }

    return objMap, nil
}
If you have m fields and n names then you are iterating O(m * n) times. For all fields and names, circa 60 * 60 = 3600 times. Only loop O(m) times:
for field, _ := range m {
    if !names[field] {
        delete(m, field)
    }
}

With some improvements:
package main

import (
    &quot;encoding/json&quot;
    &quot;fmt&quot;
    &quot;regexp&quot;
    &quot;strings&quot;
)

var fieldNameRegex = regexp.MustCompile(`^\w+$`)

func structToMap(client interface{}, fieldNames []string) (map[string]interface{}, error) {
    names := make(map[string]bool, len(fieldNames))
    for _, name := range fieldNames {
        name = strings.TrimSpace(name)
        if !fieldNameRegex.MatchString(name) {
            return nil, fmt.Errorf(&quot;Invalid field name: `%s`&quot;, name)
        }
        name = strings.ToLower(name)
        names[name] = true
    }

    j, err := json.Marshal(client)
    if err != nil {
        return nil, err
    }
    m := map[string]interface{}{}
    err = json.Unmarshal(j, &amp;m)
    if err != nil {
        return nil, err
    }
    for field, _ := range m {
        if !names[field] {
            delete(m, field)
        }
    }
    if len(m) != len(names) {
        return nil, fmt.Errorf(&quot;field(s) not found&quot;)
    }
    return m, nil
}

type Client struct {
    AltAddress string `json:&quot;alt_address&quot;`
    Firstname  string `json:&quot;firstname&quot;`
    Lastname   string `json:&quot;lastname&quot;`
}

func main() {
    client := Client{
        AltAddress: &quot;HalLo&quot;,
        Lastname:   &quot;smith&quot;,
    }

    m, err := structToMap(client, []string{&quot;alt_address&quot;, &quot;firstname&quot;})
    if err != nil {
        fmt.Println(&quot;error1:&quot;, err)
        return
    }
    j, err := json.Marshal(m)
    if err != nil {
        fmt.Println(&quot;error2:&quot;, err)
        return
    }
    fmt.Println(string(j))
}

Playground: https://play.golang.org/p/Qf8bdygEcVT
{&quot;alt_address&quot;:&quot;HalLo&quot;,&quot;firstname&quot;:&quot;&quot;}