lua代码规范
[TOC]
命名
- 小写蛇形命名
- 文件和目录名
- 本地变量,全局变量
g_
开头
local my_var = 0
g_my_var = 0
- 大写蛇形命名
- 全局常量,以
G_
开头
- 全局常量,以
G_SERVER_ID = 1
- 全局枚举,以
E_
开头且_TYPE
结尾
E_SERVER_TYPE = {
LOGIN = 1,
GAME = 2,
GLOBAL = 3,
}
- bool类型变量,使用正向命名
-- bad local fail = false if not fail then -- do something end
-- good local succ = true if succ then -- do something end
排版
- 在逗号之后添加一个空格
-- bad
local t = {1,2,3}
-- good
lcoal t = {1, 2, 3}
- 在运算符、赋值符和连接符前后各添加一个空格
-- bad
local sum = 1+2
-- good
local sum = 1 + 2
- 如查不能突出前后对齐关系,则应该避免对齐声明
-- bad
local a = 1
local var_name = 2
-- good
func(a, b, c)
func(var_name, b, c)
- 函数调用,不能省略括号
-- bad
func a, b, c
-- good
func(a, b, c)
- 不同逻辑代码块之间要空行
-- bad
function remove(list, n)
if n <= 0 then
return 0
end
table.sort(list, function(a, b)
return a.id < b.id
end
for i = 1, n do
local sz = #list
if sz > 0 then
table.remove(list, sz)
end
end
return
end
-- good
function remove(list, n)
if n <= 0 then
return
end
table.sort(list, function(a, b)
return a.id < b.id
end
for i = 1, n do
local sz = #list
if sz > 0 then
table.remove(list, sz)
end
end
end
- 代码尽可能减少缩进 ```lua – bad if a ~= nil then if b ~= nil then – do someting end end
– good if a ~= nil and b ~= nil then – do someting end
# 设计
* 使用`_`表示未被使用的变量
```lua
-- good
local list = {1, 2, 3, ...}
for _, v in pairs(list) do
print(v)
end
-- good
local _, n = string.gsub("aabbc", "a", "")
- 私有对象使用
_
前缀命名
local M= {}
function M:init()
self.a = 0
-- good
self._b = 0 -- 私有变量
end
-- good
function M:_func()
end
return M
- 遍历配置表/数据库数据,v值尽量命名为
row
-- good
for _, row in pairs(Config.ItemConfig) do
...
end
-- good
local row_list = db:find_all(...)
for _, row in pairs(row_list) do
...
end
- 尽早验证并返回
-- bad
function enter_room(role, room_id)
local cfg = Config.RoomConfig[room_id]
if cfg ~= nil then
local ok = role:cost_item(cfg.cost_item)
if ok then
....
return true
else
return false
end
else
return fasle
end
return false
end
-- good
function enter_room(role, room_id)
local cfg = Config.RoomConfig[room_id]
if cfg == nil then
return false
end
local ok = role:cost_item(cfg.cost_item)
if not ok then
return false
end
....
return true
end
- 与业务处理有强相关的函数,尽可能返回错误码
-- bad
function can_send_chat(role)
-- 角色禁言
local is_ban = role:is_chat_ban()
if is_ban then
return false
end
-- 聊天CD时间
local now = os.time()
if role.chat_cd > 0 and role.chat_cd < now then
return false
end
return true
end
-- good
function can_send_chat(role)
-- 角色禁言
local is_ban = role:is_chat_ban()
if is_ban then
return E_ERR_TYPE.CHAT_BAN
end
-- 聊天CD时间
local now = os.time()
if role.chat_cd > 0 and role.chat_cd < now then
return E_ERR_TYPE.CHAT_CD
end
return E_ERR_TYPE.SUCCESS
end
- 跨行定义table变量,需要在末尾添加
,
-- bad
local t = {
a = 1
}
-- good
local t = {
a = 1,
}
-- bad
local t = {a = 1,}
-- good
local t = {a = 1}
- 变量类型不要混合nil和false的含义
--bad
function can_get_mail(mail, role)
local now = os.time()
if now >= mail.expire_ts then
return
end
if role.create_ts > mail.create_ts then
return
end
return true
end
--good
function can_get_mail(mail, role)
local now = os.time()
if now >= mail.expire_ts then
return false
end
if role.create_ts > mail.create_ts then
return false
end
return true
end
- 变量的作用域尽量小
-- bad
function upgrade_equip(role, equip_id)
local equip_obj = role:get_equip(equip_id)
local cfg = Config.EquipConfig[equip_id]
if cfg == nil then
return E_ERR_TYPE.CONIFG_ERR
end
return equip_obj:upgrade()
end
-- good
function upgrade_equip(role, equip_id)
local cfg = Config.EquipConfig[equip_id]
if cfg == nil then
return E_ERR_TYPE.CONIFG_ERR
end
local equip_obj = role:get_equip(equip_id)
return equip_obj:upgrade()
end
- 变量的作用域在多个代码块,需要顶行声明且用空行分隔
-- bad
function buy_item(role, item_id, count)
local shop_obj = role.shop
local is_shelf = shop_obj:is_item_shelf(item_id)
if not is_shelf then
return E_ERR_TYPE.SHOP_ITEM_OFF_SHELVES
end
local remain_count = shop_obj:get_remain_count(item_id)
if remain_count < count then
return E_ERR_TYPE.SHOP_BUY_COUNT_LIMIT
end
....
end
-- good
function buy_item(role, item_id, count)
local shop_obj = role.shop
local is_shelf = shop_obj:is_item_shelf(item_id)
if not is_shelf then
return E_ERR_TYPE.SHOP_ITEM_OFF_SHELVES
end
local remain_count = shop_obj:get_remain_count(item_id)
if remain_count < count then
return E_ERR_TYPE.SHOP_BUY_COUNT_LIMIT
end
....
end
- 非业务全局函数,文件名以变量名称定义,且方法以
.
声明
-- file: table.lua
function table.shuffle()
....
end
-- file: string.lua
function string.split()
....
end
- 批量操作的代码顺序,要与代码声明顺序保持一致
local M = {}
function M:init()
self.a = 0
self.b = 0
self.c = 0
end
-- bad
function M:destroy()
self.b = 0
self.a = 0
self.c = 0
end
-- good
function M:copy(right)
self.a = right.a
self.b = right.b
self.c = right.c
end
return M
- 针对业务的全局函数
- 文件名以xxx_helper的格式定义
- 方法以
:
声明,用以区分非业务全局函数 - 为了减少全局变量污染,有需要使用的地方才会将xxx_helper对象require进来,所以xxx_helper需要在最后返回对象
-- file: mail_helper.lua
local M = {}
function M:send_mail(role_id, mail_id, ...)
end
-- 其它声明的函数
return M
-
尽量不要在多层嵌套作用域中退出函数 ```lua function foo() if … then if … then – bad return true end end
for _, i in pairs(list) do for _, j in pairs(batch) do if … then – bad return false end end end
return true end
function foo() local result = false if … then if … then – good result = true end end
for _, i in pairs(list) do
for _, j in pairs(batch) do
if ... then
-- good
result = false
break
end
end
end
return result end
* 不要直接在事件通知函数,处理业务
```lua
-- bad
function M:on_xx_timer()
-- do something here
end
-- good
function M:do_foo()
-- do something here
end
function M:on_xx_timer()
self:do_foo()
end
注释
- 注释
--
后,需要空格
-- bad
local v = 1 --v is a number
-- good
local v = 1 -- v is a number
- 文件头
--- summary.
-- Description; this can extend over
-- several lines
-- @script xxx.lua
-- @author xxx
- 函数
--- split a string in two.
-- It is a specialized splitting operation on a string.
-- @param [type=string] s the string
-- @param [type=string] delim the delimiter (default space)
-- @return first part
-- @return second part
-- @usage local hello,world = split2("hello world")
funtion split(s, delim) .. end
....
end
@param 的参数类型
类型 | type |
---|---|
整数 | int |
浮点数 | float |
字符串 | string |
函数 | function |
表 | table |
协程 | coroutine |
指针 | userdata |
- 数组&哈希表
--bad
function M:init()
self.battle_map = {}
self.battle_list = {}
end
-- good
function M:init()
-- <battle_id:int, battle_tb:table> battle_tb结构: self:new_battle_struct()
self.battle_map = {}
-- {v1:table, v2:table, ...} 元素结构: self:new_battle_struct()
self.battle_list = {}
end
function M:new_battle_struct()
return {
...
}
end
缩写
原文:
https://lizijie.github.io/2022/06/05/lua%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83.html
作者github:
https://github.com/lizijie
PREVIOUS数值程序化 lua中的load运用