how to implement the python `zip` function in golang?
Question: Sometimes, it's convenient to combine two lists into a tuple using `zip`
built-in function in Python. How to make this similarly in golang?


Answer: You could do something like [this](http://play.golang.org/p/CYtr4Z-UQ-), where
you give the tuple type a name:

    
    
    package main
    
    import "fmt"
    
    type intTuple struct {
        a, b int
    }
    
    func zip(a, b []int) ([]intTuple, error) {
    
        if len(a) != len(b) {
            return nil, fmt.Errorf("zip: arguments must be of same length")
        }
    
        r := make([]intTuple, len(a), len(a))
    
        for i, e := range a {
            r[i] = intTuple{e, b[i]}
        }
    
        return r, nil
    }
    
    func main() {
        a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
        b := []int{0, 9, 8, 7, 6, 5, 4, 3, 2, 1}
        fmt.Println(zip(a, b))
    }
    

Or alternatively use an unnamed type for the tuple, like
[this](http://play.golang.org/p/afX6bxzWRd):

    
    
    package main
    
    import "fmt"
    
    func zip(a, b []int) ([][3]int, error) {
    
        if len(a) != len(b) {
            return nil, fmt.Errorf("zip: arguments must be of same length")
        }
    
        r := make([][4]int, len(a), len(a))
    
        for i, e := range a {
            r[i] = [2]int{e, b[i]}
        }
    
        return r, nil
    }
    
    func main() {
        a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
        b := []int{0, 9, 8, 7, 6, 5, 4, 3, 2, 1}
        fmt.Println(zip(a, b))
    }
    

And finally [here's](http://play.golang.org/p/4M8yXQaLe_) a soft-generic way
of doing it:

    
    
    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    func zip(a, b, c interface{}) error {
    
        ta, tb, tc := reflect.TypeOf(a), reflect.TypeOf(b), reflect.TypeOf(c)
    
        if ta.Kind() != reflect.Slice || tb.Kind() != reflect.Slice || ta != tb {
            return fmt.Errorf("zip: first two arguments must be slices of the same type")
        }
    
        if tc.Kind() != reflect.Ptr {
            return fmt.Errorf("zip: third argument must be pointer to slice")
        }
    
        for tc.Kind() == reflect.Ptr {
            tc = tc.Elem()
        }
    
        if tc.Kind() != reflect.Slice {
            return fmt.Errorf("zip: third argument must be pointer to slice")
        }
    
        eta, _, etc := ta.Elem(), tb.Elem(), tc.Elem()
    
        if etc.Kind() != reflect.Array || etc.Len() != 2 {
            return fmt.Errorf("zip: third argument's elements must be an array of length 2")
        }
    
        if etc.Elem() != eta {
            return fmt.Errorf("zip: third argument's elements must be an array of elements of the same type that the first two arguments are slices of")
        }
    
        va, vb, vc := reflect.ValueOf(a), reflect.ValueOf(b), reflect.ValueOf(c)
    
        for vc.Kind() == reflect.Ptr {
            vc = vc.Elem()
        }
    
        if va.Len() != vb.Len() {
            return fmt.Errorf("zip: first two arguments must have same length")
        }
    
        for i := 0; i < va.Len(); i++ {
            ea, eb := va.Index(i), vb.Index(i)
            tt := reflect.New(etc).Elem()
            tt.Index(0).Set(ea)
            tt.Index(1).Set(eb)
            vc.Set(reflect.Append(vc, tt))
        }
    
        return nil
    }
    
    func main() {
    
        a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
        b := []int{0, 9, 8, 7, 6, 5, 4, 3, 2, 1}
        c := [][2]int{}
    
        e := zip(a, b, &c)
    
        if e != nil {
            fmt.Println(e)
            return
        }
    
        fmt.Println(c)
    }
    

