Groovy闭包-缺少属性

时间:2019-02-13 21:06:03

标签: jenkins groovy closures

在将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)

如何解决此错误?

1 个答案:

答案 0 :(得分:1)

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

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

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

analyze(this.&firstScore)

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

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

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

最后但并非最不重要的一点。仔细阅读"Best Practices for Scalable Pipeline Code"博客文章。它解释了编写Jenkins管道代码的最佳实践。另外,您需要意识到以下事实:流水线代码在has a bunch of limitations的Groovy CPS模式下执行。了解它们将帮助您解决从Groovy跳转到管道代码后肯定会遇到的问题。