# 代碼規范
其實選擇`OpenResty`的同學,應該都是對執行性能、開發效率比較在乎的,而對于代碼風格、規范等這些`小事`不太在意。作為一個從Linux C/C++轉過來的研發,腳本語言的開發速度,接近C/C++的執行速度,在我輕視了代碼規范后,一個BUG的發生告訴我,沒規矩不成方圓。
既然我們玩的是`OpenResty`,那么很自然的聯想到,`OpenResty`自身組件代碼風格是怎樣的呢?
> lua-resty-string 的 string.lua
~~~
local ffi = require "ffi"
local ffi_new = ffi.new
local ffi_str = ffi.string
local C = ffi.C
local setmetatable = setmetatable
local error = error
local tonumber = tonumber
local _M = { _VERSION = '0.09' }
ffi.cdef[[
typedef unsigned char u_char;
u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len);
intptr_t ngx_atoi(const unsigned char *line, size_t n);
]]
local str_type = ffi.typeof("uint8_t[?]")
function _M.to_hex(s)
local len = #s * 2
local buf = ffi_new(str_type, len)
C.ngx_hex_dump(buf, s, #s)
return ffi_str(buf, len)
end
function _M.atoi(s)
return tonumber(C.ngx_atoi(s, #s))
end
return _M
~~~
代碼雖短,但我們可以從中獲取很多信息:
1. 沒有全局變量,所有的變量均使用`local`限制作用域
1. 提取公共函數到本地變量,使用本地變量緩存函數指針,加速下次使用
1. 函數名稱全部小寫,使用下劃線進行分割
1. 兩個函數之間距離兩個空行
這里的第2條,是有爭議的。當你按照這個方式寫業務的時候,會有些痛苦。因為我們總是把標準API命名成自己的別名,不同開發協作人員,命名結果一定不一樣,最后導致同一個標準API在不同地方變成不同別名,會給開發造成極大困惑。
因為這個可預期的麻煩,我們沒有遵循第2條標準,尤其是具體業務上游模塊。但對于被調用的次數比較多基礎模塊,可以使用這個方式進行調優。其實這里最好最完美的方法,應該是Lua編譯成Luac的時候,直接做Lua Byte Code的調優,直接隱藏這個簡單的處理邏輯。
有關更多代碼細節,其實我覺得主要還是多看寫的漂亮的代碼,一旦看他們看的順眼、形成習慣,那么就很自然能寫出風格一致的代碼。規定的條條框框死記硬背總是很不爽的,所以多去看看春哥開源的`resty`系列代碼,順手品一品一下不同組件的玩法也別有一番心得。
說說我上面提及的因為風格問題造出來的坑吧。
~~~
local
function test()
-- do something
end
function test2()
-- do something
end
~~~
這是我當時不記得從哪里看到的一個`Lua`風格,在被引入項目初期,自我感覺良好。可突然從某個時間點開始,新合并進來的代碼無法正常工作。查看最后的代碼發現原來是`test()`函數作廢,被刪掉,手抖沒有把上面的`local`也刪掉。這個隱形的`local`就作用到了下一個函數,最終導致異常。
- 序
- Lua簡介
- Lua環境搭建
- 基礎數據類型
- 表達式
- 控制結構
- if/else
- while
- repeat
- 控制結構for的使用
- break,return
- Lua函數
- 函數的定義
- 函數的參數
- 函數的返回值
- 函數回調
- 模塊
- String庫
- Table庫
- 日期時間函數
- 數學庫函數
- 文件操作
- 元表
- 面向對象編程
- FFI
- LuaRestyRedisLibrary
- select+set_keepalive組合操作引起的數據讀寫錯誤
- redis接口的二次封裝(簡化建連、拆連等細節)
- redis接口的二次封裝(發布訂閱)
- pipeline壓縮請求數量
- script壓縮復雜請求
- LuaCjsonLibrary
- json解析的異常捕獲
- 稀疏數組
- 空table編碼為array還是object
- 跨平臺的庫選擇
- PostgresNginxModule
- 調用方式簡介
- 不支持事務
- 超時
- 健康監測
- SQL注入
- LuaNginxModule
- 執行階段概念
- 正確的記錄日志
- 熱裝載代碼
- 阻塞操作
- 緩存
- sleep
- 定時任務
- 禁止某些終端訪問
- 請求返回后繼續執行
- 調試
- 調用其他C函數動態庫
- 我的lua代碼需要調優么
- 變量的共享范圍
- 動態限速
- shared.dict 非隊列性質
- 如何添加自己的lua api
- 正確使用長鏈接
- 如何引用第三方resty庫
- 使用動態DNS來完成HTTP請求
- 緩存失效風暴
- Lua
- 下標從1開始
- 局部變量
- 判斷數組大小
- 非空判斷
- 正則表達式
- 不用標準庫
- 虛變量
- 函數在調用代碼前定義
- 抵制使用module()函數來定義Lua模塊
- 點號與冒號操作符的區別
- 測試
- 單元測試
- API測試
- 性能測試
- 持續集成
- 灰度發布
- web服務
- API的設計
- 數據合法性檢測
- 協議無痛升級
- 代碼規范
- 連接池
- c10k編程
- TIME_WAIT問題
- 與Docker使用的網絡瓶頸
- 火焰圖
- 什么時候使用
- 顯示的是什么
- 如何安裝火焰圖生成工具
- 如何定位問題