[英]Golang for seems to be skipping some entities
所以我有一個這樣的out
字符串:
out :=
"mobile" + "\n" +
"mobile/communicators" + "\n" +
"mobile/communicators/mock" + "\n" +
"mobile/handlers" + "\n" +
"mobile/mocks" + "\n" +
"mobile/models" + "\n" +
"mobile/requests"
我試圖將其轉換為切片,然后刪除pkgsToIgnore
切片中具有匹配子字符串的pkgsToIgnore
:
pkgs := strings.Split(strings.TrimSpace(string(out)), "\n")
pkgsToIgnore := []string{"mock", "models"}
for i, pkg := range pkgs {
for _, pkgToIgnore := range pkgsToIgnore {
if strings.Contains(pkg, pkgToIgnore){
pkgs = append(pkgs[:i], pkgs[i+1:]...)
}
}
}
for _, pkg := range pkgs {
fmt.Println(pkg)
}
然后這是我從Println
迭代中得到的結果:
mobile
mobile/communicators
mobile/handlers
mobile/models
mobile/requests
我的代碼似乎適用於包含mock
作為子字符串的行,因為它們被刪除了。 但我不明白為什么mobile/models
沒有。
查看正在發生的事情的最簡單方法是在每次迭代期間輸出i
和pkg
,即
for i, pkg := range pkgs {
fmt.Println(i, pkg)
for _, pkgToIgnore := range pkgsToIgnore {
if strings.Contains(pkg, pkgToIgnore) {
pkgs = append(pkgs[:i], pkgs[i+1:]...)
}
}
}
這個的輸出是:
0 mobile
1 mobile/communicators
2 mobile/communicators/mock
3 mobile/mocks
4 mobile/requests
5 mobile/requests
6 mobile/requests
這可能不是您所期望的! 原因是您在迭代它的同時從pkgs
中刪除元素。 讓我們在 i = 2 時解決這個問題; pkg
== "mobile/communicators/mock" 所以字符串將從pkgs
刪除。 pkgs
元素 2 現在是“移動/處理程序”。 我們循環到for
並移動到下一個元素 (3),即“移動/模擬”(不是“移動/處理程序”——現在是元素 2,因此“移動/處理程序”不會被檢查)。
go 規范的相關部分可能有助於理解這一點:
對於數組、數組指針或切片值 a,索引迭代值按遞增順序生成,從元素索引 0 開始。如果最多存在一個迭代變量,則范圍循環生成從 0 到 len( a)-1 並且不索引到數組或切片本身。 對於 nil 切片,迭代次數為 0。
可以像這樣在循環中更新切片,但這樣做 需要小心; 通常將要保留的元素復制到新切片中更簡單。
有幾種方法可以做到這一點而不會意外跳過元素。 一種方法是簡單地將您想要的元素復制到臨時切片中,然后在完成所有操作后替換原始元素(這樣更難犯錯誤)。 但是,如果您不喜歡那樣,使用兩個索引會有所幫助:
src, dst := 0, 0
for src < len(pkgs) {
var ignored bool
for _, pkgToIgnore := range pkgsToIgnore {
if strings.Contains(pkg, pkgToIgnore) {
ignored = true
break
}
}
if !ignored {
pkgs[dst] = pkgs[src]
dst += 1
}
src += 1
}
pkgs = pkgs[:dst]
src
范圍從 0 到pkgs
的最后一個索引; dst
將始終小於或等於src
(因此我們永遠不會覆蓋我們尚未見過的元素); 每個元素只復制一次,到其最終目的地,而不是每次刪除一個元素時將所有元素左移一個(這可能是二次的)。 切片的長度只在最后調整,以反映實際保留的元素數量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.