6

ここから削除の例を使用して、スライスから複数のアイテムを削除しようとしています: http://code.google.com/p/go-wiki/wiki/SliceTricks ここに私が持っているコードがあります:

package main

import "fmt"
import "net"

func main() {
    a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
    fmt.Println(a)
    for index, element := range a {
        if net.ParseIP(element).To4() == nil {
            //a = append(a[:index], a[index+1:]...)
            a = a[:index+copy(a[index:], a[index+1:])]
        }
    }
    fmt.Println(a)
}

スライスに IPv6 アドレスが 1 つしかない場合はコードが正常に機能しますが、IPv6 アドレスが複数ある場合は失敗します。「パニック: ランタイム エラー: スライス境界が範囲外」というエラーで失敗します。すべての IPv6 アドレスを削除できるように、このコードを修正するにはどうすればよいですか?

4

2 に答える 2

15

あなたの問題は、反復しているスライスを変更していることです。以下は、少し変更されたコードです。

package main

import (
    "fmt"
    "net"
)

func main() {
    a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
    fmt.Println(a)
    for i := 0; i < len(a); i++ {
        if net.ParseIP(a[i]).To4() == nil {
            a = append(a[:i], a[i+1:]...)
            //a = a[:i+copy(a[i:], a[i+1:])]
            i-- // Since we just deleted a[i], we must redo that index
        }
    }
    fmt.Println(a)
}

遊び場

于 2013-11-13T12:47:25.890 に答える
2

ポイントを上げると、繰り返している構造を変更するのは常に難しいことです。
これを回避する一般的な方法は、最終結果を新しい変数で構築することです。

package main

import (
    "fmt"
    "net"
)

func main() {
    a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
    fmt.Println(a)

    var b []string
    for _, ip := range a {
        if net.ParseIP(ip).To4() != nil {
                b = append(b, ip)
        }
    }
    fmt.Println(b)
}

http://play.golang.org/p/7CLMPw_FQi

于 2013-11-13T13:38:55.680 に答える