Deleting VALUE from a KEY within MAP with custom []type


(Ross Bown) #1

I have a map of type []keyValue like so :

var data map[string][]keyValue

the below struct is the custom slice of type in the map above. This is intended to allow multiple data types to be saved to a map. There is only ever one instance of a key, but a list of many values and data types.

type keyValue struct {
String string

Integer   int
IntegerOK bool

Float   float64
FloatOK bool

Boolean   bool
BooleanOK bool
}

I want to be able to delete the VALUE out of the above map… so for example:
KEY: DOG VALUE: zeus
KEY: DOG VALUE: true

If I wanted to delete true, what would be the best code to use?

Before updating the code to accept multiple data types into the map, the below code worked… by iterating over the specific key, and then getting the index value of what was entered into the URL and simply moving it out

func deleteKeyValue(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)

k := params["key"]
v := params["value"]

//delete the value
if v != "" {
    if _, ok := data[k]; ok {
        for i := range data[k] {
            data[k] = append(data[k][:i], data[k][i+1:]...)
        }
        fmt.Fprintf(w, "KEY: %v, VALUE: %v has been deleted from the Key-Value store", k, v)
    } else {
        fmt.Fprintf(w, "That Key-Value pairing doesn't exist in the Key-Value store")
    }

Now when the above code runs, using the new datatype on the MAP, i get the below error:

2019/01/09 19:59:03 http: panic serving [::1]:53122: runtime error: slice bounds out of range goroutine 4 [running]: net/http.(*conn).serve.func1(0xc000110000) C:/Go/src/net/http/server.go:1746 +0xd7


(Ignacio Gómez) #2

If I understand what you want, you need to check against the type and value on your range and delete on match, something like this (I skipped the conversions for brevity):

shouldDelete := false
for i, keyValue := range data[k] {
  if keyValue.IntegerOk {
    //Convert v to int and compare
    //If it corresponds, set shouldDelete to true
  } else if keyValue.FloatOk {
    //Convert v to float and compare
    //If it corresponds, set shouldDelete to true
  } else if keyValue.BooleanOk {
    //Convert v to bool and compare
    //If it corresponds, set shouldDelete to true
  }
  if shouldDelete {
    if len(data[k]) - 1 == i {
      data[k] = data[k][:i]
    } else {
      data[k] = append(data[k][:i], data[k][i+1:]...)
    }
    fmt.Fprintf(w, "KEY: %v, VALUE: %v has been deleted from the Key-Value store", k, v)
    break
  }
}
if !shouldDelete {
//There was no element that matched the value, print some message saying this.
fmt.Fprintf(w, "KEY: %v, VALUE: %v wasn't found in the Key-Value store", k, v)
}

I’m assuming that the Ok fields indicate the type of the value, and that each instance only allows one to be true. Adapt it accordingly if that’s not the case.

This snippet also adds a check to see if the match occurs on the last element of the slice, in which case you just need to subslice it from the start to the element before last. If you don’t check and it’s indeed the last element that matches, data[k][i+1:] will panic, as you’re out of the slice’s bounds, i.e., data[k][i+1] is beyond the slice’s end.


(Ross Bown) #3

Thank you so much for your help! Glad you understood my question, and the example you have given is exactly what I needed! Appreciate your help.