2017-02-26 44 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()函数通过返回接口{}来工作,但是使用该函数的结果需要做一个类型断言。所以,如果你可以避免它,你应该使用类型搜索另一个解决方案。

相关问题