Golang中如何从自定义类型MAP中删除指定KEY的VALUE

Golang中如何从自定义类型MAP中删除指定KEY的VALUE 我有一个类型为 []keyValue 的映射如下:

var data map[string][]keyValue

下面的结构体是上述映射中的自定义切片类型。这样设计的目的是允许在映射中存储多种数据类型。每个键只存在一个实例,但可以有多个值和数据类型。

type keyValue struct {
String string

Integer   int
IntegerOK bool

Float   float64
FloatOK bool

Boolean   bool
BooleanOK bool
}

我希望能够从上述映射中删除值…例如: 键:DOG 值:zeus 键:DOG 值:true

如果我想删除 true,应该使用什么最佳代码?

在更新代码以接受映射中的多种数据类型之前,以下代码可以正常工作…通过遍历特定键,然后获取 URL 中输入内容的索引值并简单地将其移出

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

k := params["key"]
v := params["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")
    }

现在当上述代码运行时,使用映射上的新数据类型,我收到以下错误:

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


更多关于Golang中如何从自定义类型MAP中删除指定KEY的VALUE的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

非常感谢您的帮助!很高兴您理解了我的问题,您给出的示例正是我需要的!感谢您的帮助。

更多关于Golang中如何从自定义类型MAP中删除指定KEY的VALUE的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果我理解正确的话,你需要检查遍历中的类型和值,并在匹配时进行删除,类似这样(为简洁起见我省略了类型转换):

shouldDelete := false
for i, keyValue := range data[k] {
  if keyValue.IntegerOk {
    //将v转换为int并比较
    //如果匹配,将shouldDelete设为true
  } else if keyValue.FloatOk {
    //将v转换为float并比较
    //如果匹配,将shouldDelete设为true
  } else if keyValue.BooleanOk {
    //将v转换为bool并比较
    //如果匹配,将shouldDelete设为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 {
//没有匹配值的元素,打印提示信息
fmt.Fprintf(w, "KEY: %v, VALUE: %v wasn't found in the Key-Value store", k, v)
}

我假设Ok字段表示值的类型,并且每个实例只允许一个为真。如果不是这种情况,请相应调整。

这段代码还添加了一个检查,看匹配是否发生在切片的最后一个元素上,如果是这种情况,你只需要从开始到倒数第二个元素进行切片。如果不检查且确实是最后一个元素匹配,data[k][i+1:] 将会panic,因为你超出了切片的边界,即 data[k][i+1] 超出了切片的末尾。

在Go语言中,从自定义类型映射中删除指定键的值时,需要正确处理切片操作以避免索引越界错误。以下是修复后的代码示例:

func deleteKeyValue(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    
    k := params["key"]
    v := params["value"]
    
    if v != "" {
        if values, ok := data[k]; ok {
            // 创建新切片保存保留的值
            var newValues []keyValue
            
            // 遍历所有值,只保留不匹配的值
            for _, kv := range values {
                shouldDelete := false
                
                // 检查各种数据类型的值是否匹配
                if kv.String == v {
                    shouldDelete = true
                } else if kv.BooleanOK && strconv.FormatBool(kv.Boolean) == v {
                    shouldDelete = true
                } else if kv.IntegerOK && strconv.Itoa(kv.Integer) == v {
                    shouldDelete = true
                } else if kv.FloatOK && strconv.FormatFloat(kv.Float, 'f', -1, 64) == v {
                    shouldDelete = true
                }
                
                if !shouldDelete {
                    newValues = append(newValues, kv)
                }
            }
            
            // 更新映射中的值
            if len(newValues) == 0 {
                delete(data, k)
            } else {
                data[k] = newValues
            }
            
            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")
        }
    }
}

或者使用更简洁的索引删除方法:

func deleteKeyValue(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    
    k := params["key"]
    v := params["value"]
    
    if v != "" {
        if values, ok := data[k]; ok {
            for i := 0; i < len(values); i++ {
                kv := values[i]
                shouldDelete := false
                
                if kv.String == v {
                    shouldDelete = true
                } else if kv.BooleanOK && strconv.FormatBool(kv.Boolean) == v {
                    shouldDelete = true
                } else if kv.IntegerOK && strconv.Itoa(kv.Integer) == v {
                    shouldDelete = true
                } else if kv.FloatOK && strconv.FormatFloat(kv.Float, 'f', -1, 64) == v {
                    shouldDelete = true
                }
                
                if shouldDelete {
                    // 从切片中删除元素
                    values = append(values[:i], values[i+1:]...)
                    i-- // 调整索引,因为切片长度减少了
                }
            }
            
            // 更新映射
            if len(values) == 0 {
                delete(data, k)
            } else {
                data[k] = values
            }
            
            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")
        }
    }
}

原代码的问题在于使用了错误的切片删除逻辑。data[k] = append(data[k][:i], data[k][i+1:]...) 在循环中会破坏切片结构,导致索引越界。修复后的代码正确处理了各种数据类型的值比较和切片删除操作。

回到顶部