-
序
- 入门篇
- Lua 入门
-
Nginx
-
Nginx 新手起步
-
location 匹配规则
-
静态文件服务
-
日志
-
反向代理
-
负载均衡
-
陷阱和常见错误
- 环境搭建
-
Hello World
-
与其他 location 配合
-
获取 uri 参数
-
获取请求 body
-
输出响应体
-
日志输出
-
简单API Server框架
-
使用 Nginx 内置绑定变量
-
子查询
-
不同阶段共享变量
-
防止 SQL 注入
-
如何发起新 HTTP 请求
-
访问有授权验证的 Redis
-
select+set_keepalive 组合操作引起的数据读写错误
-
redis 接口的二次封装(简化建连、拆连等细节)
-
redis 接口的二次封装(发布订阅)
-
pipeline 压缩请求数量
-
script 压缩复杂请求
-
动态生成的 lua-resty-redis 模块方法
-
Nginx 新手起步
- LuaCjsonLibrary
- PostgresNginxModule
- LuaNginxModule
- LuaRestyDNSLibrary
- LuaRestyLock
- 测试
- Web 服务
- 火焰图
调用代码前先定义函数
Lua 里面的函数必须放在调用的代码之前,下面的代码是一个常见的错误:
-- test.lua 文件
local i = 100
i = add_one(i)
function add_one(i)
return i + 1
end
copy
我们将得到如下错误:
# luajit test.lua
luajit: test.lua:2: attempt to call global 'add_one' (a nil value)
stack traceback:
test.lua:2: in main chunk
[C]: at 0x0100002150
copy
为什么放在调用后面就找不到呢?原因是 Lua 里的 function 定义本质上是变量赋值,即
function foo() ... end
copy
等价于
foo = function () ... end
copy
因此在函数定义之前使用函数相当于在变量赋值之前使用变量,Lua 世界对于没有赋值的变量,默认都是 nil,所以这里也就产生了一个 nil 的错误。
一般地,由于全局变量是每个请求的生命期,因此以此种方式定义的函数的生命期也是每个请求的。为了避免每个请求创建和销毁 Lua closure 的开销,建议将函数的定义都放置在自己的 Lua module 中,例如:
-- my_module.lua
local _M = {_VERSION = "0.1"}
function _M.foo()
-- your code
print("i'm foo")
end
return _M
copy
然后,再在 content_by_lua_file
指向的 .lua
文件中调用它:
local my_module = require "my_module"
my_module.foo()
copy
因为 Lua module 只会在第一次请求时加载一次(除非显式禁用了 lua_code_cache
配置指令),后续请求便可直接复用。