Skip to content

Instantly share code, notes, and snippets.

@czlc
Last active January 4, 2018 07:59
Show Gist options
  • Save czlc/4eb8d65eea94d2dbba6d534367e6e436 to your computer and use it in GitHub Desktop.
Save czlc/4eb8d65eea94d2dbba6d534367e6e436 to your computer and use it in GitHub Desktop.
luacs

Lua 代码风格指南

格式化

  • 行首使用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规则

https://en.wikipedia.org/wiki/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规则

https://en.wikipedia.org/wiki/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"

skynet

  • 不要在循环中调用别的服务;callsend都应避免
-- 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操作

参考

  1. Lua Style Guide@lua-users.org
  2. Lua Style Guide@github.com/Olivine-Labs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment