功能

函数是编程的基本构建块 —— 它们是对执行任务的语句进行分组的一种方便而强大的方法。它们是 NetScaler 设备和扩展代码之间的接口。对于策略,您可以定义策略扩展功能。对于协议,您可以为协议行为实现回调函数。函数由函数定义组成,这些定义指定传入和传出函数的值以及为函数运行哪些语句;函数调用,函数调用运行具有特定输入数据的函数并从函数中获取结果。

协议行为回调函数

TCP 客户端行为由处理 TCP 客户端数据流事件的回调函数 (on_data) 组成。要为基于 TCP 的协议实现基于消息的负载平衡 (MBLB),您可以为此回调函数添加代码,以处理来自客户端的 TCP 数据流并将字节流解析为协议消息。

行为中的回调函数是通过上下文调用的,上下文是处理模块状态。上下文是处理模块的实例。例如,对于不同的客户端 TCP 连接,使用不同的上下文调用 TCP 客户端行为回调。

除了上下文之外,行为回调还可以有其他参数。通常,其余的参数作为有效载荷传递,这是所有参数的集合。因此,可编程处理模块实例可以看作是实例状态加上事件回调函数的组合,即上下文加行为。流量作为事件有效载荷通过管道。

TCP 客户端回调函数的原型:



                Function                client on_data (ctxt, payload)

                                                //.code

                end


<!--NeedCopy-->

其中,

  • ctxt -TCP 客户端处理上下文
  • 有效载荷 -事件负载
    • payload.data-接收的 TCP 数据,以字节流的形式提供

策略扩展功能

由于键入了 NetScaler 策略表达式语言,因此扩展函数的定义必须指定其输入的类型和返回值。L ua 函数 定义已扩展为包括以下类型:


function self-type: function-name(parameter1: parameter1-type, and so on): return-type
     statements
end

<!--NeedCopy-->

其中,

这些类型是 NSTEXT、NSNUM、NSBOOL 或 NSDOUBLE。

Sself-type 是传递给函数的隐式自身参数的类型。在 NetScaler 策略表达式中使用扩展函数时,这是函数左侧的表达式生成的值。另一种查看方法是,该函数在 NetScaler 策略语言中扩展了该类型。

参数类型是策略表达式中扩展函数调用中指定的每个参数的类型。扩展函数可以有零个或多个参数。

return 类型是扩展函数调用返回的值的类型。它是函数右侧策略表达式部分(如果有)的输入,否则是表达式结果的值。

示例:

function NSTEXT:COMBINE_HEADERS() : NSTEXT

在策略表达式中使用扩展功能:

HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n").COMBINE_HEADERS()

这里的自我参数是的结果 HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n"),这是一个文本值。COMBINE_HEADERS () 调用的结果是文本,并且由于此调用右侧没有任何内容,因此整个表达式的结果为文本。

局部函数定义

除了扩展函数之外,扩展文件中不能定义全局函数。但是局部函数可以使用普通的 Lua 函数语句在扩展函数中定义。这会声明函数的名称及其参数的名称(也称为参数),并且像 Lua 中的所有声明一样,不指定任何类型。这样做的语法是:


local function function-name(parameter1-name, parameter2-name, and so on)
     statements
end

<!--NeedCopy-->

函数和参数名称都是标识符。(函数名实际上是一个变量,函数语句是局部函数名 = function(参数1 等)的简写,但是您不必理解这种微妙之处就可以使用函数。)

请注意,这里使用等等来延续参数名称的模式,而不是通常的…。这是因为… 本身实际上意味着一个变量参数列表,这里不会讨论。

函数体和返回

函数和 end 语句之间的语句块是函数体。在函数体中,函数参数的作用类似于局部变量,其值由函数调用提供,如前所述。

return 语句提供要返回给函数调用者的值。它必须出现在块的末尾(在函数中,如果是,for 循环等)。它可以在自己的区块中返回… 结束)。它指定没有、一个或多个返回值:


return -- returns nil
return expression -- one return value
return expression1, expression2, ... -- multiple return values

<!--NeedCopy-->

示例:


local function fsum(a)
     local sum = 0
     for i = 1, #a do
          sum = sum + a[i]
     end
     return sum
end

Local function fsum_and_average(a)
     local sum = 0
     for i = 1, #a do
          sum = sum + a[i]
     end
     return sum, sum/#a
end

<!--NeedCopy-->

函数调用

函数调用运行函数的主体,为函数的参数提供值并接收结果。函数调用的语法是函数名称(expression 1、expression 2 等),其中函数参数被设置为相应的表达式。表达式和参数的数量不必相同。如果表达式少于参数,则剩余的参数将设置为 nil。因此,您可以在调用结束时将一个或多个参数设置为可选参数,然后您的函数可以通过检查它们是否为 nil 来检查它们是否被指定。执行此操作的常见方法是使用 OR 操作:


function f(p1, p2) -- p2 is optional
     p2 = p2 or 0 -- if p2 is nil, set to a default of 0
     . . .
end

<!--NeedCopy-->

如果表达式多于参数,则会忽略剩余的表达式值。

如前所述,函数可以返回多个值。这些返回值可以在多重赋值语句中使用。示例:


local my_array = {1, 2, 3, 4}
local my_sum, my_ave = sum_and_average(my_array)

<!--NeedCopy-->

迭代器函数和泛型 for 循环

现在我们已经引入了函数,我们可以谈谈泛型 for 循环。泛型 for 循环(包含一个变量)的语法为:


for variable in iterator(parameter1, parameter2, and so on) do
     statements in the for loop body
end

<!--NeedCopy-->

其中 iterator () 是一个具有零个或多个参数的函数,这些参数在循环体的每次迭代中为变量提供一个值。迭代器函数使用一种叫做闭包的技术来跟踪它在迭代中的位置,在这里您不必担心。它通过返回 nil 来表示迭代结束。迭代器函数可以返回多个值,用于多重赋值。

编写迭代器函数超出了本文的范围,但是很少有用的内置迭代器来说明这个概念。一个是 pairs () 迭代器,它遍历表中的条目并返回两个值,即键和下一个条目的值。

示例:


local t = {k1 = "v1", k2 = "v2", k3 = "v3"}
local a = {} -- array to accumulate key-value pairs
local n = 0 -- number of key-value pairs
for key, value in pairs(t) do
     n = n + 1
     a[n] = key.. " = ".. Value -- add key-value pair to the array
end
local s = table.concat(a, ";") -- concatenate all key-value pairs into one string

<!--NeedCopy-->

另一个有用的迭代器是 string.gmatch() 函数,它在下面的 COMBINE_HEADERS() 示例中使用。

功能