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