将切片转换为元组的便捷功能?

时间:2013-09-30 20:38:25

标签: go

在Python中,可以编写这样的代码,从列表中分配多个值:

(a, b, c, d) = [1,2,3,4]

是否有一组类似的Go库函数用于切片?也就是说,我可以这样做: http://play.golang.org/p/DY1Bi5omm1

package main

func get3(s []interface{}) (
    a interface{},
    b interface{},
    c interface{},
    rest []interface{}) {
  return s[0],s[1],s[2],s[4:]
}

func main() {  
  s := make([]interface{},5);
  for i :=0 ; i < 5; i++ { s[i] = i}
  a,b,c,_ := get3(s)

  print(a.(int))
  print(b.(int))
  print(c.(int))
}

有没有一种标准的gophery方式来做到这一点?

有没有办法绕过界面{}丑陋?

2 个答案:

答案 0 :(得分:1)

不是那样的;你需要动态类型或参数多态,这在Go中是不可用的。我能想到的最接近的是摆弄反射,如:http://play.golang.org/p/-K4jh2nZjq

// src is supposed to be []T.
// dst are supposed to be &T, except the last one, which must be a 'rest' &[]T (or nil for discarding).
// There must not be more dst vars than elements in src.
func extract(src interface{}, dst ...interface{}) {
    srcV := reflect.ValueOf(src)
    // Iterate over dst vars until we run out of them.
    i := 0
    for i = 0; i < len(dst)-1; i++ {
        reflect.Indirect(reflect.ValueOf(dst[i])).Set(srcV.Index(i))
    }

    // Now, the rest.
    restDst := dst[i]
    if restDst == nil {
        return
    }
    restV := reflect.ValueOf(restDst)
    indirectRest := reflect.Indirect(restV)
    l := srcV.Len() - i
    indirectRest.Set(reflect.MakeSlice(restV.Type().Elem(), 0, l))
    for ; i < srcV.Len(); i++ {
        itemV := srcV.Index(i)
        indirectRest.Set(reflect.Append(indirectRest, itemV))
    }
    return
}

然后你打电话给:

sl := []int{1, 2, 3, 4, 5, 6} // int or any other type
var a, b, c int
var rest []int
extract(sl, &a, &b, &c, &rest)

所以丑陋并不能解决这个问题。

但请注意所有在运行时发生的事情,因此它不安全也不高效,绝对不是惯用的Go。

答案 1 :(得分:1)

我认为你不能,至少不是以惯用/干净的方式。您可以执行多项任务,但您必须直接或使用闭包传递单个值:

package main

import (
  "fmt"
)

func valuesFromList(list[]int,startFrom int) func() int  {
  i:=startFrom
  return func() int {
    ret := list[i]
    i++
    return ret
  }
}


func main () {
  list := []int{0,1,2,3,4,5,6,7,8,9}
  yield := valuesFromList(list,5)

  //This works
  a,b,c := yield(),yield(),yield()
  fmt.Println(a)
  fmt.Println(b)
  fmt.Println(c)

  //This also works
  d,e,f := list[0],list[1],list[2]
  fmt.Println(d)
  fmt.Println(e)
  fmt.Println(f)
  //This won't work
  //g,h,i:= list[7:9]
}