2017-02-26 37 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

注意,這失去了編譯時類型安全,因爲它必須使用的接口。另外,由於使用接口,可能會分配浮動值,從而產生額外的GC壓力。

Common Go風格通常建議不寫這樣的函數,並且隻手動插入少量代碼。

0

畢竟,這真的很好使用反射awers我也想添加一個答案,提供了一個更習慣性的Go解決方案。像羅布派克在他的大談Go Proverbs

  • 接口說{}也不說
  • 反思是從來沒有明確

所以應該會有一個也回答顯示了慣用的去路。此解決方案不適用於標準類型的切片。但有cshu的回答顯示出最佳的解決方案: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

錯誤說,關於這個問題的一切:不能使用POP(一)(類型接口{})在指定int類型:need type assertion

所以Pop()函數通過返回接口{}來工作,但是使用該函數的結果需要做一個類型斷言。所以,如果你可以避免它,你應該使用類型搜索另一個解決方案。