- 行首使用4字母缩进(Lua 推荐的是2字母)
- 行长度不要超过80个字符
- 不要用分号避免换行
-- bad
local whatever = 'sure';
a = 1; b = 2
-- good
local whatever = 'sure'
a = 1
b = 2
- 不要因为代码块较短,就写成一行
-- bad
local print_table = function(t) for _,v in ipairs(t) do print(v) end end
-- good
local print_table = function(t)
for _,v in ipairs(t) do
print(v)
end
end
{
,}
,及所有运算符前后应留一个空格
-- bad
local test={one=1}
local thing=1
thing = thing-1
thing = thing*1
thing = 'string'..'s'
--good
local test = { one = 1 }
local thing = 1
thing = thing - 1
thing = thing * 1
thing = 'string' .. 's'
(
,)
前后不留空格- 逗号后空一格
- 代码块之间留一个空行
-- bad
if thing then
-- ...stuff...
end
function derp()
-- ...stuff...
end
local wat = 7
-- good
if thing then
-- ...stuff...
end
function derp()
-- ...stuff...
end
local wat = 7
- 字符串推荐使用双引号(")
-
作用范围越大的变量、函数,名字应该越具体(即越长)
-
文件、变量、函数名称遵循
snake_case
规则
-- bad
local OBJEcttsssss = {}
local thisIsMyObject = {}
local this-is-my-object = {}
local c = function()
-- ...stuff...
end
-- good
local this_is_my_object = {}
local function do_that_thing()
-- ...stuff...
end
- 常量名称使用全大写字母,单词之间用下划线分隔
--good
local MAX_COUNT = 200
-
下划线开头的变量名保留给lua内部使用,如
_G
和_ENV
-
使用单下划线表示忽略的变量
--good
for _, name in pairs(names) do
-- ...stuff...
end
- 类、模块名称遵循
PascalCase
规则
-- bad
local date = require('date')
local mongo_obj = require "mongo_obj"
-- good
local Date = require('date')
local MongoObj = require "mongo_obj"
- 不要使用隐式类型转换
local input_value = '4'
-- bad
local total_score = review_score .. ''
local val = input_value * 1
-- good
local total_score = tostring(review_score)
local val = tonumber(input_value)
- 除了错误处理分支,尽量不用
debug
库
- 变量声明时总是使用
local
, 避免产生全局变量 - 不要定义不使用的变量;忽略的变量命名为
_
; - 不要使用未定义变量
- 在作用域的顶部给变量赋值,避免随用随取
-- bad
for _, item in ipairs(items) do
if item.score > player:get_score() then
-- do something
end
end
-- good
local score = player:get_score()
for _, item in ipairs(items) do
if item.score > score then
-- do something
end
end
- 合理减小变量的作用域
-- bad
local v, x, y, z
if condition then
x = u2*v3-u3*v2
y = u3*v1-u1*v3
z = u1*v2-u2*v1
v = {x,y,z}
end
-- good
local v
if condition then
local x = u2*v3-u3*v2
local y = u3*v1-u1*v3
local z = u1*v2-u2*v1
v = {x,y,z}
end
- 函数声明时总是使用
local
, 避免产生全局函数
-- bad
function foo()
-- stuff
end
-- good
local function foo()
-- stuff
end
- 优先使用函数语法;避免产生匿名函数
-- bad
local nope = function(name, options)
-- ...stuff...
end
-- good
local function yup(name, options)
-- ...stuff...
end
- 早失败,早返回; 减少嵌套层次;
-- bad
local function is_good_name(name)
if #name >= 3 then
if #name <= 30 then
if not string.match(name, "%u") then
return true
end
end
end
return false
end
-- good
local function is_good_name(name, options, args)
if #name < 3 or #name > 30 or string.match(name, "%u") then
return false
end
return true
end
- 函数循环复杂度尽量低于10,不应超过15
循环复杂度定义: https://zh.wikipedia.org/wiki/%E5%BE%AA%E7%92%B0%E8%A4%87%E9%9B%9C%E5%BA%A6
- 建议优先使用
OOP
模式设计系统 - 类的私有成员函数名字使用下划线开头
- 模块不要直接返回非基类
- 类的对象应使用同一个元表
-- bad
-- foo.lua
local mt = {}
function mt:_do_foo()
-- stuff
end
function mt:foo()
-- stuff
self:_do_foo()
-- stuff
end
local M = {}
function M.new_obj()
local obj = {
-- stuff
}
return setmetatable(obj, {__index=mt})
end
return M
-- good
-- foo.lua
local mt = {}
mt.__index = mt
function mt:_do_foo()
-- stuff
end
function mt:foo()
-- stuff
self:_do_foo()
-- stuff
end
local M = {}
function M.new_obj()
local obj = {
-- stuff
}
return setmetatable(obj, mt)
end
return M
- 外部不要直接访问/修改类的成员变量; 如果外部需要频繁访问类的成员变量,需要考虑一下类的内聚性。
-- bad
local obj = new_obj()
print(obj.score)
obj.score = 5
-- good
local obj = new_obj()
print(obj:get_score())
obj:set_score(5)
- 模块总是返回一个
table
- 建议模块内待返回的
table
使用local M = {}
声明方式
- 通过
require
引用的模块,应该按照通用性由高到底排序 - 通用模块、业务模块、服务内模块之间应使用空行分隔
-- bad
local RoomApi = require "room_api"
local RoomConst = require "war_room.const"
local Env = require "global"
local Date = require "date"
local Log = require "log"
-- good
local Log = require "log"
local Date = require "date"
local RoomApi = require "room_api"
local RoomConst = require "war_room.const"
local Env = require "global"
- 不要在循环中调用别的服务;
call
和send
都应避免
-- bad
for _, item in ipairs(items) do
Skynet.call(addr, "lua", "add_item", {item_id=item.item_id})
end
-- good
local request = {}
for _, item in ipairs(items) do
table.insert(request, {item_id=item.item_id})
end
Skynet.call(addr, "lua", "add_items", request)
- 不要在循环中进行
io
操作