2017-02-26 6 views
1
a := []int{1,2,3} 
x, a := a[len(a)-1], a[:len(a)-1] 
fmt.Println(a,x) 

pop()関数を作成して、どのタイプの配列でも同じようにする方法はありますか?pop()関数の書き方

func pop(a []*interface{}) interface{}{ 
    x := a[len(a)-1] 
    a = a[:len(a)-1] 
    return x 
} 

func main(){ 
    a := []int{1,2,3} 
    x = pop(a) 
    fmt.Println(a,x) // -> [1,2] 3 
} 

しかし、私は試行錯誤によってコードを微調整しようとする場合、私はcannot use a (type []int) as type []interface {}または他のエラーメッセージが出ます:ここで

は、私がこれまでに思い付いたものです。

答えて

2
package main 

import (
    "fmt" 
    "reflect" 
) 

func pop(a interface{}) interface{} { 
    v := reflect.ValueOf(a).Elem() 
    x := v.Index(v.Len() - 1) 
    v.SetLen(v.Len() - 1) 
    return x 
} 

func main() { 
    a := []int{1, 2, 3} 
    x := pop(&a) 
    fmt.Println(a, x) // -> [1,2] 3 
} 

これを実装することができますが、私はまだx, a = a[len(a)-1], a[:len(a)-1]ポップ関数よりも良いはずだと思います。

0

ゴー型システムでは、[]type1 -> []type2からキャストすることはできません。それがなかった場合でも、インターフェースは通常、あなただけのオブジェクトを持つことになり、オブジェクトへのid型とポインタを含む構造体です。このため、あなたはinterface{}を取り、スライスを行うことを反映使用する必要があります。

func pop(slice interface{}) (interface{}, interface{}) { 
    v := reflect.ValueOf(slice) 
    return v.Slice(0,v.Len()-1).Interface(), v.Index(v.Len()-1).Interface() 
} 

Go Playground

それはインタフェースを使用しなければならないので、これは、時の型の安全性をコンパイル失うことに注意してください。また、poped値インターフェースを使用することにより、余分なGC圧力を作成、割り当てられてもよいです。

共通ゴースタイルは、一般的にこのような関数を書いていないことをお勧めします、とだけ手動で少量のコードをインライン化。

0

反射を使って本当に良いanwersは、私はまた、よりイディオムGoソリューションを提供する一つの答えを追加したいと思います。ロブ・パイクは、彼の偉大な話についてGo Proverbs

  • インタフェースに言ったように{}何
  • 反射が明らかになることはありませんと言う

そうもがなければならないGoらしい道を示す1つの答え。このソリューションは、標準的なタイプのスライスでは動作しません。しかし、最善の解決策を示してcshuのが答え:私たちはPOPERインターフェイスとポップの機能を定義する必要が独自定義型のx, a = a[len(a)-1], a[:len(a)-1]

は、入力としてあることを取り、空のインターフェイスを返します。

type Poper interface { 
    Pop() interface{} 
} 

type MyType struct { 
    a []int 
} 

func (mt *MyType) Pop() interface{} { 
    x := mt.a[len(mt.a)-1] 
    mt.a = mt.a[:len(mt.a)-1] 
    return x 
} 

func Pop(p Poper) interface{} { 
    return p.Pop() 
} 

func main() { 
    a := &MyType{[]int{1, 2, 3}} 
    fmt.Println(Pop(a), a) 
} 

https://play.golang.org/p/UbDkoVYSMA

以下のすべてのコードは、{}インタフェースをサポートする必要があるためで全ては、空のインタフェースを返すために、良いアイデアではありません。

次のコード例では動作しない。

func main() { 
    a := &MyType{[]int{1, 2, 3}} 
    fmt.Println(Pop(a), a) 
    var b int 
    b = Pop(a) 
} 

https://play.golang.org/p/wg9__O44A8

エラーは、その問題についてのすべてを言う:は、割り当てにint型としてポップ(A)(式インターフェースを{})を使用することができません:型アサーションが必要です

したがって、Pop()関数はinterface {}を返すことによって動作しますが、その関数の結果を使用する残りのコードは型アサーションを行う必要があります。だからあなたがそれを避けることができるなら、あなたはタイプを使って別の解決策を探さなければなりません。

関連する問題