首页 > 解决方案 > Groovy 闭包 - 缺少属性

问题描述

在将 jenkins 管道编写为脚本之前,尝试学习 groovy 闭包。

下面的代码:

def scores = [72,29,32,44,56]

def analyse(closure){
    closure(scores)
}

def firstScore(array){
    return array[0]
}

analyse(firstScore)

给出错误:

groovy.lang.MissingPropertyException: No such property: firstScore for class: groovy.lang.Binding
    at groovy.lang.Binding.getVariable(Binding.java:63)

如何解决此错误?

标签: jenkinsgroovyclosures

解决方案


您会看到此错误,因为firstScore在您的代码示例中它是一个方法而不是一个闭包。您可以将firstScore定义从方法更改为闭包,例如

def firstScore = { array ->
    return array[0]
}

或者您可以使用将方法转换为闭包的Groovy方法指针运算符。在这种情况下,您必须通过analyze以下方式调用方法:

analyze(this.&firstScore)

除此之外 - 您的 Groovy 脚本仍然会失败。您尝试访问方法scores内部analyze。您需要知道脚本中定义的任何方法都会自动提升为类级别的方法(每个 Groovy 脚本都会编译为扩展类的groovy.lang.Script类)。您在 Groovy 脚本主体中定义的所有其他表达式和语句都是方法的一部分,Script.run()并且它们在本地范围内。所以当方法Script.analyze()被调用时,它会抱怨不存在的属性scores,因为scores它在方法的本地范围内Script.run()。要修复它,您可以使用将局部变量转换为类级别属性scores的注释来注释变量- 在这种情况下,可以从任何方法访问。@groovy.transform.Fieldscores

您可以在下面找到策划脚本的示例:

import groovy.transform.Field

@Field
def scores = [72,29,32,44,56]

def analyse(closure){
    closure(scores)
}

def firstScore(array){
    return array[0]
}

println analyse(this.&firstScore)

输出:

72

最后但并非最不重要。仔细阅读“可扩展管道代码的最佳实践”博客文章。它解释了编写 Jenkins 管道代码的最佳实践。此外,您需要了解这样一个事实,即管道代码在 Groovy CPS 模式下执行,这有很多限制。了解它们将帮助您解决从 Groovy 跳转到管道代码后肯定会遇到的问题。


推荐阅读