【问题标题】:How to make a function accept any type array as param in GO? [duplicate]如何使函数接受任何类型的数组作为 GO 中的参数?
【发布时间】:2022-01-05 11:45:12
【问题描述】:

我需要创建一个将任何类型数组作为参数的函数。

package main

import "fmt"

type flt func(interface{}) bool

func filter(sl []interface{}, f flt) (filtered []interface{}) {
    // todo call flt to each element on array
    return
}

func f1(interface{}) bool{
    return true
}

func main() {
    slice := []int{1, 2, 3, 4, 5, 7}
    filter(slice, f1)
}
./prog.go:16:8: cannot use slice (type []int) as type []interface {} in argument to filter

我创建了这个question,但该解决方案不适用于数组。

编辑1。顺便说一句,您可能注意到了,但我正在尝试为任何数组创建一个“映射函数”,就像 JS array.filter()

【问题讨论】:

  • 泛型将在下一个版本 1.18(下个月)中出现,然后您将能够传递任何切片并返回相同元素类型的切片。在那之前,您一直坚持将参数定义为 interface{} 并使用反射来迭代其元素。不用说,它不如泛型解决方案。
  • 您当然可以更有效地处理“一对”具体切片类型(使用类型断言或类型切换),但绝对不是所有切片类型。
  • 在过滤功能中,只需将[]interface{}改为interface{}go.dev/play/p/1Hahj5OpBNK
  • 这能回答你的问题吗? How can I implement a generic filter function?

标签: arrays function go types interface


【解决方案1】:

我对 Interface{} 的使用有误。不用我说它是一个数组,只要一个普通的 Interface{} 就可以接收任何类型的切片。

就像 icza 说的我使用反射来获取 Interface{} 的类型,但是通过使用“reflect.TypeOf(el).Kind() != reflect.Slice”,我避免了手动类型处理程序并获得了我的一般功能就像我想要的那样。

package main

import (
    "errors"
    "reflect"
)

type flt func(interface{}) bool

func filter(el interface{}, f flt) (filtered interface{}, err error) {
    if reflect.TypeOf(el).Kind() != reflect.Slice {
        err = errors.New("Passed element is not an slice")
        filtered = el
        return
    }
    // todo -> apply flt to each element from array
    return
}

func f1(interface{}) bool {
    return true
}

func main() {
    slice := []int{1, 2, 3, 4, 5, 7}
    slice2 := []string{"1", "2", "a"}
    filter(slice, f1)
    filter(slice2, f1)
    filter(1, f1)
}

也检查一下: How to check if interface{} is a slice

【讨论】:

    【解决方案2】:

    你仍然可以使用反射

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type flt func(interface{}) bool
    
    func filter(sl interface{}, f flt) interface{} {
        v := reflect.ValueOf(sl)
        filtered := reflect.MakeSlice(v.Type(), 0, v.Len()-1)
        for i := 0; i < v.Len(); i++ {
            if f(v.Interface()) {
                filtered = reflect.Append(filtered, v.Index(i))
            }
        }
    
        return filtered.Interface()
    }
    
    func f1(interface{}) bool {
        return true
    }
    
    func main() {
        slice := []int{1, 2, 3, 4, 5, 7}
        filtered := filter(slice, f1)
        for _, v := range filtered.([]int) {
            fmt.Printf("Filtered value: %v\n", v)
        }
    }
    

    https://go.dev/play/p/hmzgUD8ceb1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      相关资源
      最近更新 更多