localStorage.getItem('asdf')
如何为任何类型的数组创建一个a := []int{1,2,3}
x, a := a[len(a)-1], a[:len(a)-1]
fmt.Println(a,x)
函数?
这是我到目前为止所提出的:
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
}
或其他错误消息。
答案 0 :(得分: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]
应该优于pop函数。
答案 1 :(得分:0)
go类型系统不允许你从[]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()
}
请注意,这会丢失编译时类型安全性,因为它必须使用接口。此外,由于使用接口,可以分配poped值,从而产生额外的GC压力。
Common Go风格通常建议不要编写这样的函数,只是手动内联少量代码。
答案 2 :(得分:0)
在使用反射完成所有非常好的回答后,我还想添加一个答案,提供更具惯用性的Go解决方案。就像Rob Pike在他关于Go Proverbs
的精彩演讲中所说的那样所以应该有一个答案显示惯用的Go方式。此解决方案不适用于标准类型的切片。但是 cshu 的答案显示了最佳解决方案:b
对于自己定义的类型,我们必须定义一个Poper接口,Pop函数将其作为输入并返回一个空接口。
2.0
https://play.golang.org/p/UbDkoVYSMA
返回空接口并不是一个好主意,因为以下所有代码都必须支持接口{}。
以下代码示例不起作用:
x, a = a[len(a)-1], a[:len(a)-1]
https://play.golang.org/p/wg9__O44A8
错误说明了该问题:不能在赋值中使用Pop(a)(类型接口{})作为int类型:need type assertion
所以Pop()函数通过返回接口{}来工作,但是使用该函数的结果的其余代码需要进行类型断言。因此,如果您可以避免它,您应该使用类型搜索另一个解决方案。