如何仅使用1种方法删除不同类型的切片

时间:2018-08-17 13:24:32

标签: go slice type-assertion

我有2个go函数,例如以下

 func removeL2McEntry(a []api.L2McEntry, index int) []api.L2McEntry {
    a = append(a[:index], a[index+1:]...) 
    element
    return a[:len(a)]
 }

 func removeVlagBasedGroup(a []api.VlanPortBased, index int) []api.VlanPortBased {
    a = append(a[:index], a[index+1:]...) 
    return a[:len(a)]
 }

如您所见,这两个功能都在做相同的工作。但是我需要将它们分开,因为函数的输出和输入是不同的类型。

我尝试过:

func removeSlice(a interface{}, idx int) interface{} {
    switch v := a.(type) { 
    case []string:
        v = append(v[:idx], v[idx+1:]...) 
        fmt.Println("is ary", v)
        return v[:len(v)]
    case []int:
        v = append(v[:idx], v[idx+1:]...) 
        fmt.Println("is ary", v)
        return v[:len(v)]
    default:

    }
    return nil
}

但是用这种方式的重复代码太多了。 有什么方法可以使它成为一个功能并减少重复的代码?

谢谢。

1 个答案:

答案 0 :(得分:2)

正如阿德里安(Adrian)所说,从切片中删除元素通常是一行代码:

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: -34.397, lng: 150.644},
          zoom: 8
        });

    var kmlLayer = new google.maps.KmlLayer();
    var src = 'https://www.voanaboa.pt/Files/downloads/Regulamento-RPA-ver-5.0.kmz';
    var kmlLayer = new google.maps.KmlLayer(src, {
        //suppressInfoWindows: true,
        preserveViewport: false,
        map: map
    });
  }
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&libraries=geometry&callback=initMap"
async defer></script>

为它编写一个函数真的不值得,只需在需要的地方使用此代码段即可。

如果确实需要创建一个可以处理任何切片类型的函数,则可以使用反射来创建它。但是使用它时,您将必须在结果上使用类型断言,因为该函数只能返回静态类型a = append(a[:i], a[i+1]...) // or a = a[:i+copy(a[i:], a[i+1:])] 。比在您的具体切片值上使用上面的代码段还要慢!

可以使用reflect包“复制”上述删除步骤。切片是Value.Slice()方法,附加操作是reflect.AppendSlice()函数。

这是它的外观(省略类型和绑定检查):

interface{}

测试:

func remove(s interface{}, i int) interface{} {
    v := reflect.ValueOf(s)
    return reflect.AppendSlice(v.Slice(0, i), v.Slice(i+1, v.Len())).Interface()
}

输出(在Go Playground上尝试):

is := []int{0, 1, 2, 3}
is = remove(is, 2).([]int)
fmt.Printf("%#v\n", is)

ss := []string{"0", "1", "2", "3"}
ss = remove(ss, 2).([]string)
fmt.Printf("%#v\n", ss)

但是再说一次:我不建议任何人使用此(尽管有效)代码,只需直接使用原始代码段删除该元素即可。