千家信息网

OpenResty编码有哪些规范

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,这篇文章给大家介绍OpenResty编码有哪些规范,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。本编码规范由 APISIX 编写和维护。很多开发语言都有自己的编码规范,来告诉开发
千家信息网最后更新 2025年12月02日OpenResty编码有哪些规范

这篇文章给大家介绍OpenResty编码有哪些规范,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

本编码规范由 APISIX 编写和维护。

很多开发语言都有自己的编码规范,来告诉开发者这个领域内的约定俗成,让大家写的代码看上去风格保持一致,并且避免一些常见的陷阱,这些对于新手都是非常友好的,可以让初学者快速的上手。比如 Python 的 PEP 80,就是其中的典范,几乎所有的 Python 开发者都阅读过这份 Python 作者执笔的编码规范。

让开发者统一思想,按照规范来写代码,是一件非常重要的事情。OpenResty 还没有自己的编码规范,有些开发者在提交 PR 后,会在代码风格上被反复 review 和要求修改,消耗了大量本可以避免的时间和精力。

其实,在 OpenResty 中有两个可以帮你自动化检测代码风格的工具:luacheck 和 lj-releng。前者是 Lua 和 OpenResty 世界通用的检测工具,后者是 OpenResty 自己用 perl 写的代码检测工具。对于我自己而言,我会在 vs code 编辑器中安装 luacheck 的插件,这样我写代码的时候就有工具来自动提示;而在项目的 CI 中,则是会把这两个工具都运行一遍,比如:

luacheck -q lua./utils/lj-releng lua/*.lua lua/apisix/*.lua 复制代码

多一个工具的检测总不是坏事。

但这两个工具更多的是检测全局变量、每行长度等这些最基础的代码风格,离 Python pep80 的详细程度还有遥远的距离,并且也没有文档给你做参考。

今天我就根据自己在 OpenResty 相关开源项目中的经验,总结下 OpenResty 的编码风格文档,这个规范也和一些常见的 API 网关:Kong、APISIX 的代码风格是一致的。

缩进

在 OpenResty 中使用 4 个空格作为缩进的标记,虽然 Lua 并没有这样的语法要求。

--Noif a thenngx.say("hello")end复制代码
--yesif a then    ngx.say("hello")end复制代码

你可以在使用的编辑器中,把 tab 改为 4 个空格,来简化操作。

空格

在操作符的两边,都需要用一个空格来做分隔:

--Nolocal i=1local s    =    "apisix"复制代码
--Yeslocal i = 1local s = "apisix"复制代码

空行

不少开发者会把其他语言的开发习惯带到 OpenResty 中来,比如在行尾增加一个分号。

--Noif a then    ngx.say("hello");end;复制代码

增加分号会让 Lua 代码显得非常丑陋,也是没有必要的。另外,不要为了节省代码的行数,后者为了显得"简洁",而把多行代码变为一行。这样会在定位错误的时候不知道到底那一段代码出了问题:

--Noif a then ngx.say("hello") end复制代码
--yesif a then    ngx.say("hello")end复制代码

函数之间需要用两个空行来做分隔:

--Nolocal function foo()end local function bar()end复制代码
--Yeslocal function foo()end local function bar()end复制代码

如果有多个 if elseif 的分支,它们之间需要一个空行来做分隔:

--Noif a == 1 then        foo()   elseif a== 2 then        bar()   elseif a == 3 then        run()   else        error()end复制代码
--Yesif a == 1 then        foo()        elseif a== 2 then        bar()        elseif a == 3 then        run()        else        error()end复制代码

每行最大长度

每行不能超过 80 个字符,超过的话,需要换行并对齐:

--No return limit_conn_new("plugin-limit-conn", conf.conn, conf.burst, conf.default_conn_delay)复制代码
--Yesreturn limit_conn_new("plugin-limit-conn", conf.conn, conf.burst,                                        conf.default_conn_delay)复制代码

在换行对齐的时候,要体现出上下两行的对应关系。就上面的示例而言,第二行函数的参数,要在第一行左括号的右边。

如果是字符串拼接的对齐,需要把 .. 放到下一行中:

--No return limit_conn_new("plugin-limit-conn" ..  "plugin-limit-conn" ..                                        "plugin-limit-conn")复制代码
--Yesreturn limit_conn_new("plugin-limit-conn" .. "plugin-limit-conn"                                        .. "plugin-limit-conn")复制代码

变量

应该永远使用局部变量,不要使用全局变量:

--Noi = 1s = "apisix"复制代码
--Yeslocal i = 1local s = "apisix"复制代码

变量命名使用 snake_case 风格:

--Nolocal IndexArr = 1local str_Name = "apisix"复制代码
--Yeslocal index_arr = 1local str_name = "apisix"复制代码

对于常量要使用全部大写:

--Nolocal max_int = 65535local server_name = "apisix"复制代码
--Yeslocal MAX_INT = 65535local SERVER_NAME = "apisix"复制代码

数组

使用table.new 来预先分配数组:

--Nolocal t = {}for i = 1, 100 do   t[i] = i end复制代码
--Yes local new_tab = require "table.new" local t = new_tab(100, 0) for i = 1, 100 do   t[i] = i end复制代码

不要在数组中使用 nil:

--Nolocal t = {1, 2, nil, 3}复制代码

如果一定要使用空值,请用 ngx.null 来表示:

--Nolocal t = {1, 2, ngx.null, 3}复制代码

字符串

不要在热代码路径上拼接字符串:

--Nolocal s = ""for i = 1, 100000 do        s = s .. "a"end复制代码
--Yeslocal t = {}for i = 1, 100000 do        t[i] = "a"endlocal s =  table.concat(t, "")复制代码

函数

函数的命名也同样遵循 snake_case

--Nolocal function testNginx()end复制代码
--Yeslocal function test_nginx()end复制代码

函数应该尽可能早的返回:

--Nolocal function check(age, name)        local ret = true        if age < 20 then                ret = false        end        if name == "a" then                ret = false        end        -- do something else         return ret 复制代码
--Yeslocal function check(age, name)        if age < 20 then                return false        end        if name == "a" then                return false        end        -- do something else         return true 复制代码

模块

所有 require 的库都要 local 化:

--Nolocal function foo()        local ok, err = ngx.timer.at(delay, handler)end复制代码
--Yeslocal timer_at = ngx.timer.atlocal function foo()        local ok, err = timer_at(delay, handler)end复制代码

为了风格的统一,require 和 ngx 也需要 local 化:

--Nolocal core = require("apisix.core")local timer_at = ngx.timer.atlocal function foo()        local ok, err = timer_at(delay, handler)end复制代码
--Yeslocal ngx = ngxlocal require = requirelocal core = require("apisix.core")local timer_at = ngx.timer.atlocal function foo()        local ok, err = timer_at(delay, handler)end复制代码

错误处理

对于有错误信息返回的函数,必须对错误信息进行判断和处理:

--Nolocal sock = ngx.socket.tcp() local ok = sock:connect("www.google.com", 80) ngx.say("successfully connected to google!")复制代码
--Yeslocal sock = ngx.socket.tcp() local ok, err = sock:connect("www.google.com", 80) if not ok then         ngx.say("failed to connect to google: ", err)         return end ngx.say("successfully connected to google!")复制代码

自己编写的函数,错误信息要作为第二个参数,用字符串的格式返回:

--Nolocal function foo()        local ok, err = func()        if not ok then                return false        end        return trueend复制代码
--Nolocal function foo()        local ok, err = func()        if not ok then                return false, {msg = err}        end        return trueend复制代码
--Yeslocal function foo()        local ok, err = func()        if not ok then                return false, "failed to call func(): " .. err        end        return trueend复制代码

关于OpenResty编码有哪些规范就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

0