V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
newmiao
V2EX  ›  Go 编程语言

OPA 进阶-简洁的推导式

  •  
  •   newmiao · 2020-04-06 18:21:05 +08:00 · 1177 次点击
    这是一个创建于 1452 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文来讲讲OPA推导式( comprehensions ),主要涉及三类数据的推导式:object,array,set

    我们将以实现判断配置文件数据的不同聚合方式为例展开。

    用到的输入(配置文件列表)为:

    // input.json
    // posix 为常见路径格式
    // traditional-mac 为 mac 的一种文件路径格式
    {
      "files": [
      {
        "type": "posix",
        "path": "/Users/newbmiao/Documents/1.yaml"
      },
      {
        "type": "posix",
        "path": "/Users/newbmiao/Documents/2.yaml"
      },
      {
        "type": "traditional-mac",
        "path": "Macintosh HD:Users:newbmiao:Documents:3.yml"
      },
      {
        "type": "traditional-mac",
        "path": "Macintosh HD:Users:newbmiao:Documents:3.json"
      }
      ]
    }
    

    comprehensions

    推导式(comprehensions)提供了一种从子查询构建复合值(Composite Values)的简洁方法。

    定义很晦涩,我们从例子来看会清晰许多

    object comprehensions

    首先看一个按文件路径类型聚合文件的例子:

    import input.files
    
    group_files_by_type := {type: paths |
      file := files[_]
      type := file.type
      paths := [path |
        tmp := files[_]
        tmp.type == type
        path := tmp.path
      ]
    }
    

    即两层遍历,外层遍历获取type

    内层遍历按type匹配推导出paths数组

    对应结果为

    opa eval -f values -d . -i input.json "data.example_comprehensions.group_files_by_type"
    [
      {
        "posix": [
          "/Users/newbmiao/Documents/1.yaml",
          "/Users/newbmiao/Documents/2.yaml"
        ],
        "traditional-mac": [
          "Macintosh HD:Users:newbmiao:Documents:3.yml",
          "Macintosh HD:Users:newbmiao:Documents:3.json"
        ]
      }
    ]
    

    忽略实现细节,对象的推导式语法为:

    { <key>: <term> | <body> }

    定义的keyterm需要在body内赋值,最后会复合出一个对象,包含有所有满足的<key>: <term>

    这里要注意的事body内条件要都满足才会返回

    array comprehensions

    上边例子中paths是一个数组推导式

    其语法为: [ <term> | <body> ]

    注意这里的[], 只有数组推导式用方括号

    而且其内容是可重复的

    对应再举一个将所有文件路径转为posix的例子:

    convert_all_to_posix_path_array := [path |
      path1 := [p |
        file := files[_]
        file.type == "posix"
        p := file.path
      ]
    
      path2 := [p |
        file := files[_]
        file.type == "traditional-mac"
        p := replace(replace(file.path, "Macintosh HD", ""), ":", "/")
      ]
    
      paths := array.concat(path1, path2)
      path = paths[_]
    ]
    

    这里按文件路径类型推导出path1path2两个数组

    其内部对于file.type的判断达到了过滤匹配的作用

    set comprehensions

    上边功能也可以用集合推导式实现如下:

    convert_all_to_posix_path_sets := {path |
      path1 := {p |
        file := files[_]
        file.type == "posix"
        p := file.path
      }
    
      path2 := {p |
        file := files[_]
        file.type == "traditional-mac"
        p := replace(replace(file.path, "Macintosh HD", ""), ":", "/")
      }
    
      paths := path1 | path2
      path = paths[_]
    }
    

    集合推导式语法为:

    { <term> | <body> }

    其特点是不会重复

    可以看出同样功能,集合做组合操作比较表意

    类似的,交集可以用&,差集可以用-

    以上就是OPA三类推导式的使用方式。推导式最大的特点就是简洁。

    一旦你熟悉了,就可以写出很多优雅的聚合方式。

    最后出一个题目,大家可以自己练习下(答案可以去opa-koans中查看)

    实现基于文件后缀聚合文件路径, 即输出为:

    {
      "json": [
        "Macintosh HD:Users:newbmiao:Documents:3.json"
      ],
      "yaml": [
        "/Users/newbmiao/Documents/1.yaml",
        "/Users/newbmiao/Documents/2.yaml"
      ],
      "yml": [
        "Macintosh HD:Users:newbmiao:Documents:3.yml"
      ]
    }
    

    提示, 对于文件后缀可以用如下两种方式获取

    方式一: hardcode

    extSets := ["yaml", "yml", "json"]

    方式二:regex

    extSets := {e |
      e = regex.find_all_string_submatch_n(".*\\.(.*)$", files[_].path, -1)[0][1]
    }
    

    本文代码详见:NewbMiao/opa-koans

    下一篇,我们讲讲如何用OPA的测试和压测保证规则的正确性与效率。

    文章首发公众号:newbmiao

    推荐阅读:OPA 系列

    欢迎关注,获取及时更新内容

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1343 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:38 · PVG 07:38 · LAX 16:38 · JFK 19:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.