GoLang,切片读取错误

Posted

技术标签:

【中文标题】GoLang,切片读取错误【英文标题】:GoLang, bad readout from slice 【发布时间】:2018-09-09 11:41:20 【问题描述】:

我是 GoLang 的新手,我需要一些帮助。我正在制作简单的 API 应用程序。

通过 API 将结构传递给切片如下所示:

type Struct struct 
    //some records


var structs []Struct //slice

func SetStruct(w http.ResponseWriter, req *http.Request) 
    var st Struct
    decoder := json.NewDecoder(req.Body)
    decoder.Decode(&st)
    emails = append(structs, st)
    json.NewEncoder(w).Encode(structs)

并且该功能可以正常工作。

我想做的第二件事是从切片中删除该结构取决于NR 参数。我称之为POST。方法如下:

func SendStruct(w http.ResponseWriter, req *http.Request) 
    var st Email
    decoder := json.NewDecoder(req.Body)
    decoder.Decode(&st)
    for i, item := range emails 
        if item.NR == st.NR 
            structs = append(structs[:i], structs[i+1:]...)
            //if numbers match, delete from slice emails
        
    
    json.NewEncoder(w).Encode(emails)

当我有这样的场景时它工作得很好(例如):

"NR": "22"
"NR": "33"
"NR": "22"

当我想删除"33" 时,它工作得很好。当我想删除"22"(两者)时,事情开始变得复杂,因为当我通过22 时,应用程序崩溃了。

item.NR(来自SendStruct)中,我的变量超出范围。当我在for 中添加break 参数时,它可以正常工作,但我只能一个接一个地删除结构。我想在一次 API 调用中删除所有 22。我得到的错误:

http:panic serving [::1]:52163:运行时错误:切片超出范围

感谢您的任何建议!

【问题讨论】:

【参考方案1】:

在迭代切片时不应修改切片。 range 不知道切片现在比它开始时短,所以最终它会尝试迭代超过那个点 - 哎呀! -- 找不到更多切片了。

我建议做的是保留一个单独的切片,其中包含可以找到要删除的项目的索引列表。然后,当您完成对电子邮件切片的迭代后,您可以迭代此索引跟踪器切片并删除相关项目。确保您对索引跟踪器切片进行排序,使其从高索引变为低索引,否则您最终将相对于剩余索引点的位置缩短切片。

【讨论】:

我明白了,所以当(例如)我在数组中有 5 个结构时,我删除了第三个,它离开了范围,因为它试图进入第五个但在删除第三个之后,切片是范围是 4 而不是 5? @michasacuer 完全正确。 另一种选择是使用 3 部分 for 循环样式 for i := 0; i < len(data); i++。每次迭代都会检查 Len,从而捕获更新的索引。话虽如此,在迭代时更改切片实际上并不是破坏代码的原因。您正在迭代切片emails,但使用索引变量来索引和子切片structs。只要你只从structs 中删减一件事,这就能正常工作,但是一旦你删减了不止一个(并且在最后),你的电子邮件切片现在比结构和恐慌更长。

以上是关于GoLang,切片读取错误的主要内容,如果未能解决你的问题,请参考以下文章

在 golang 中使用私有地图、切片的最佳实践是啥?

Golang 创建切片地图

如何在golang中将切片附加到字节数组

为啥在golang中不允许对切片指针进行索引

JSON文件语法验证Golang

Golang 从切片追加函数“已评估但未使用”中删除 dup ints