OpenResty 中的 Lua 编码规范
点击“阅读原文”,可以查看 GitHub 上的原文。
-
缩进
在 OpenResty 中使用 4 个空格作为缩进的标记,虽然 Lua 并没有这样的语法要求。
--No
if a then
ngx.say("hello")
end
--yes
if a then
ngx.say("hello")
end
你可以在使用的编辑器中,把 tab 改为 4 个空格,来简化操作。
-
空格
在操作符的两边,都需要用一个空格来做分隔:
--No
local i=1
local s = "apisix"
--Yes
local i = 1
local s = "apisix"
-
空行
不少开发者会把其他语言的开发习惯带到 OpenResty 中来,比如在行尾增加一个分号。
--No
if a then
ngx.say("hello");
end;
增加分号会让 Lua 代码显得非常丑陋,也是没有必要的。另外,不要为了节省代码的行数,后者为了显得“简洁”,而把多行代码变为一行。这样会在定位错误的时候不知道到底那一段代码出了问题:
--No
if a then ngx.say("hello") end
--yes
if a then
ngx.say("hello")
end
函数之间需要用两个空行来做分隔:
--No
local function foo()
end
local function bar()
end
--Yes
local function foo()
end
local function bar()
end
如果有多个 if elseif 的分支,它们之间需要一个空行来做分隔:
--No
if a == 1 then
foo()
elseif a== 2 then
bar()
elseif a == 3 then
run()
else
error()
end
--Yes
if 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)
--Yes
return limit_conn_new("plugin-limit-conn", conf.conn, conf.burst,
conf.default_conn_delay)
在换行对齐的时候,要体现出上下两行的对应关系。就上面的示例而言,第二行函数的参数,要在第一行左括号的右边。
如果是字符串拼接的对齐,需要把 .. 放到下一行中:
<span>--No</span>
<span><span>return</span> limit_conn_new(<span>"plugin-limit-conn"</span> .. <span>"plugin-limit-conn"</span> ..</span>
<span> <span>"plugin-limit-conn"</span>)</span>
<span></span>
<span>--Yes</span>
<span><span>return</span> limit_conn_new(<span>"plugin-limit-conn"</span> .. <span>"plugin-limit-conn"</span></span>
<span> .. <span>"plugin-limit-conn"</span>)</span>
-
变量
应该永远使用局部变量,不要使用全局变量:
--No
i = 1
s = "apisix"
--Yes
local i = 1
local s = "apisix"
变量命名使用 snake_case
风格:
--No
local IndexArr = 1
local str_Name = "apisix"
--Yes
local index_arr = 1
local str_name = "apisix"
对于常量要使用全部大写:
--No
local max_int = 65535
local server_name = "apisix"
--Yes
local MAX_INT = 65535
local SERVER_NAME = "apisix"
-
数组
使用 table.new
来预先分配数组:
--No
local 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
:
--No
local t = {1, 2, nil, 3}
如果一定要使用空值,请用 ngx.null 来表示:
--No
local t = {1, 2, ngx.null, 3}
-
字符串
不要在热代码路径上拼接字符串:
--No
local s = ""
for i = 1, 100000 do
s = s .. "a"
end
--Yes
local t = {}
for i = 1, 100000 do
t[i] = "a"
end
local s = table.concat(t, "")
-
函数
函数的命名也同样遵循 snake_case
:
--No
local function testNginx()
end
--Yes
local function test_nginx()
end
函数应该尽可能早的返回:
--No
local 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
end
--Yes
local function check(age, name)
if age < 20 then
return false
end
if name == "a" then
return false
end
-- do something else
return true
end
-
模块
所有 require 的库都要 local 化:
--No
local function foo()
local ok, err = ngx.timer.at(delay, handler)
end
--Yes
local timer_at = ngx.timer.at
local function foo()
local ok, err = timer_at(delay, handler)
end
为了风格的统一,require 和 ngx 也需要 local 化:
--No
local core = require("apisix.core")
local timer_at = ngx.timer.at
local function foo()
local ok, err = timer_at(delay, handler)
end
--Yes
local ngx = ngx
local require = require
local core = require("apisix.core")
local timer_at = ngx.timer.at
local function foo()
local ok, err = timer_at(delay, handler)
end
-
错误处理
对于有错误信息返回的函数,必须对错误信息进行判断和处理:
--No
local sock = ngx.socket.tcp()
local ok = sock:connect("www.google.com", 80)
ngx.say("successfully connected to google!")
--Yes
local 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!")
自己编写的函数,错误信息要作为第二个参数,用字符串的格式返回:
--No
local function foo()
local ok, err = func()
if not ok then
return false
end
return true
end
--No
local function foo()
local ok, err = func()
if not ok then
return false, {msg = err}
end
return true
end
--Yes
local function foo()
local ok, err = func()
if not ok then
return false, "failed to call func(): " .. err
end
return true
end