3

スライス用に、GoのJavaScriptArray.splice関数と同等のものを作成したいとします。私は次のコードを持っています:

func splice(slice []int, index, amount int, elements ...int) []int {
    newslice := make([]int, 0)
    for i := 0; i < index; i++ {
        newslice = append(newslice, slice[i])
    }
    for i := index + amount; i < len(slice); i++ {
        newslice = append(newslice, slice[i])
    }
    for _, el := range elements {
        newslice = append(newslice, el)
    }
    return newslice
}

この例は機能しますが、タイプがの引数に対してのみ機能しますint。汎用にしたいので、可変個引数の引数elementsに型interface{}を指定する必要があることはわかっていますが、関数内からそのインターフェイスの型を使用して新しいスライスを作成するにはどうすればよいですか?

言い換えると、関数の最初の行の引数のタイプに応じて、スライスのタイプを動的に指定するにはどうすればよいですか?どこnewsliceで作成されますか?

4

2 に答える 2

6

GoでJavaScriptをエミュレートする代わりに(なぜ???)、 SliceTricksの構成要素から同様の必要な操作を作成することを提案したいと思います。

彼らです:

  • 完全に不可知論者と入力します(「ジェネリック」を無料で考えてください)。
  • 内外でのパック/アンパックと比較して、おそらくかなり高速[]interface{}です。
于 2012-12-06T22:45:17.273 に答える
5

リフレクションを使用する

あなたが本当に一般的なことをしたいのなら、リフレクションは究極の答えです。 問題の詳細については、リフレクションパッケージのMakeSliceのドキュメントを参照してください。

(を使用して)着信スライスのタイプを取得し、正しくTypeOf(...)適用する必要があります。MakeSlice

リフレクションを使用してスライスを作成する例:

y := []int{1,2,3}
t := reflect.TypeOf(y)

slice := reflect.MakeSlice(t, 0, 10)
slice = reflect.Append(slice, reflect.ValueOf(2))

fmt.Println(slice.Interface())

ここで実行します

使用する[]interface{}

を使用する別の方法は、です[]interface{}。これは任意の値を格納できますが、コンパイラの型チェックを完全に省略すると、実行時のパニックにつながる可能性があります(これは悪いことです)。

[]interface{} これは、任意の値のストレージとして使用するための例です。これにより、スプライス実装のタイプを知る必要はなく、スプライスし[]interface{}て新しいスライスに使用するだけです。

[]interface{}この方法には、一部のスライスを簡単に変換できないという欠点があります。前の投稿で説明されているように、手動でコピーする必要があります。

結論

使用するバージョンに関係なく、タイプを認識して手動で変換しない限り、タイプの安全性を取り戻すことはできません。Goには、あなたに代わってそれを行うようなことはありません。つまり、型の安全性を取り戻すために、コードに次のようなものが含まれることになります。

x := []int{1,2,3,4}
y := splice(x, ...)
yn := []int(y)
于 2012-12-07T00:49:59.273 に答える