2017-08-01 75 views
0

我創建了一個小型幫助函數,將大量項目分割成最小大小爲n的較小數組。使幫助函數通用

func toPackages(e []int, n int) [][]int { 
    var p [][]int 
    packets := int(math.Ceil(float64(len(e))/float64(n))) 
    for i := 0; i < packets; i++ { 
     start := i * n 
     end := n * (i + 1) 
     if len(e) < end { 
      end = len(e) 
     } 
     p = append(p, e[start:end]) 
    } 
    return p 
} 

工作示例Golang Playground
在程序中我想分割幾種不同類型的數組。我試圖將其轉換爲使用interface{}的接口。

+0

Go沒有仿製藥。你可以使用'interface {}'或者創建一個你需要執行這個特定函數的函數。 – Adrian

回答

3

很難做出一個通用的函數來處理這個問題。您經常會花費盡可能多的代碼將[]int轉換爲[]interface{}並返回,因爲它只是複製代碼段。我有一個稍微更好的辦法,雖然做到這一點:

playground link

func splitInts(src []int, n int) (p [][]int){ 
    for len(src) > n{ 
     p = append(p,src[:n]) 
     src = src[n:] 
    } 
    if(len(src) > 0){ 
     p = append(p,src) 
    } 
    return p 
} 

,因爲類型的功能改變不了什麼,它可以很容易地被複制到:

func splitStrings(src []string, n int) (p [][]string){ 
    for len(src) > n{ 
     p = append(p,src[:n]) 
     src = src[n:] 
    } 
    if(len(src) > 0){ 
     p = append(p,src) 
    } 
    return p 
} 

僅通過改變第一行。

0

通常,爲每種需要的類型編寫函數是一個好主意。這也是一個速度問題:如果你使用反射來編寫一個通用函數,它不會那麼快。

如果你仍然想在這裏的通用功能是:

func genToPackages(e interface{}, n int) interface{} { 
    t := reflect.TypeOf(e) 
    if t.Kind() != reflect.Slice { 
     log.Println("e has to be a slice") 
    } 
    v := reflect.ValueOf(e) 

    packets := int(math.Ceil(float64(v.Len())/float64(n))) 
    p := reflect.MakeSlice(reflect.SliceOf(t), packets, packets) 
    for i := 0; i < packets; i++ { 
     s := reflect.MakeSlice(t, n, n) 
     start := i * n 
     for j := 0; j < n; j++ { 
      s.Index(j).Set(v.Index(j+start)) 
     } 

     p.Index(i).Set(s) 
    } 

    return p.Interface() 
} 

您將有結果轉換到你所期望的類型。例如:

res := genToPackages([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 5).([][]int)