# 从架构层面杜绝lua中使用未定义的变量

标签(空格分隔): lua

---

lua中有一个很坑的地方:
1.就是如果一个变量拼写错误,会自动的认为你定义了一个值为nil的全局变量.
2.如果在function中定义一个局部变量,忘记了local,则会默认为是定义成为了一个全局变量.

为了防止这种问题,我今天想到一个解决方案.
可以达到以下效果:
1.在function中使用一个未定义的变量时则报错.
2.在function中定义全局变量则报错,即全局变量中能够在全局空间中定义.

具体做法如下:
在代码初始化的时候,重写_G的__newindex,这个是在往_G中加新东西的时候会调用的,即定义全局变量的时候会调用.
首先我们用一个table来记录定义了那些全局变量,这样做的目的是,我们之后可以在使用全局变量的时候判断时候已经定义了该全局变量.所以我们还应该重写__index,这个__index是在使用表中的内容会调用的.
所以有了如下代码:
```
local tbDefineValue = {}

setmetatable(_G, {
__index = function(tb, key)
if not tbDefineValue[key] then
error(string.format("找不到全局变量:%s", key))
return nil
end
rawget(tab, key)
end,
_newindex = function(tb, key, value)
tbDefineValue[key] = true
rawset(tb, key, value)
end
}

)
```
我们把这段代码放到一个全局空间的最先require的文件里面,做初始化.
这样之后我们每定义一个全局对象都会记录.
另外,很关键的一点是:这个代码会在初始化的调用.所以之后定义的全局变量会记录,使用全局变量会检查时候有该全局变量,如果有就返回,否则报错;

然后在程序运行过程中,我们需要有一个init函数来处理.
在运行过程中,我们需要禁止创建全局变量,只能够改变现有全局变量的值或者使用现有的全局变量.
所以我们需要禁止_G的__newindex的时候去增加全局变量.
所以我们有一个```init()```函数,用于设置_G只读.
代码如下:
```
function init()
setmetatable(_G, {
__newindex = function(tb, key, value)
do return end
-- tbDefineValue[key] = true
-- rawset(tb, key, value)
end,
})
end
```
大功告成.
以下是测试用例.
```
local tbDefineValue = {}
setmetatable(_G, {
__index = function(tb, key)
if not tbDefineValue[key] then
error(string.format("can not find global:%s", key))
return nil
end
rawget(tab, key)
end,
_newindex = function(tb, key, value)
tbDefineValue[key] = true
rawset(tb, key, value)
end
}
)

function disableWrite_G()
setmetatable(_G, {
__newindex = function(tb, key, value)
error(string.format("can not define global value:%s in local space", key))
do return end
end,
})
end

c = 12
print(c)

function test2()
d = 12
c = 13
end

function test3()
print(c)
if a == 12 then
print(123)
end
end

function start()
disableWrite_G()
test2()
test3()
end

start()
```
输出结果是
```
D:\Binaries-LuaDist-batteries-0.9.8-Windows-x86\bin\lua.exe: .\test.lua:20: can not define global value锛歞 in local space
stack traceback:
[C]: in function 'error'
.\test.lua:20: in function <.\test.lua:19>
.\test.lua:30: in function 'test2'
.\test.lua:43: in function 'start'
.\test.lua:47: in main chunk
[C]: ?

```

从架构层面杜绝lua中使用未定义的变量的更多相关文章

  1. js 温故而知新 用typeof 来判断一个未定义的变量

    一直以为,如果你使用一个未定义的变量,肯定会报错.甚至根本不可能有这种场景. 但仔细想想还是有的,譬如你要判断全局是否存在$变量.或者要为全局暴漏一个全局变量之前,先判断是否有这个变量. typeof ...

  2. 五十九、SAP中常用预定义系统变量

    一.SAP中常用预定义系统变量 内容如下: 二.系统变量定义在结构SYST里,我们打开SE38 三.在代码编辑器输入SYST变量 四.双击SYST,来到这个系统结构,里面有很多系统变量 五.我们随便写 ...

  3. 关于c调用lua 对‘luaL_newstate()’未定义的引用的问题解决办法

    #include <string.h>#include "lua.h"#include "lauxlib.h"#include "lual ...

  4. 情景剧:C/C++中的未定义行为(undefined behavior)

    写在前面 本文尝试以情景剧的方式,轻松.直观地解释C/C++中未定义行为(undefined behavior)的概念.设计动机.优缺点等内容1,希望读者能够通过阅读本文,对undefined beh ...

  5. C++中的"未定义的行为"

    2.1 位运算 位运算的运算对象是整数类型的,并且把运算对象看成是一个二进制位的集合.运算对象可以是带符号也可以是无符号.如果是带符号且值为负,那么位运算如何处理运算对象的符号位依赖于机器.而且此时的 ...

  6. js在函数中未定义的变量的处理

    <html> <head> <script type="text/javascript"> var z=1; function abc(){ x ...

  7. WPF/UWP 的 Grid 布局竟然有 Bug,还不止一个!了解 Grid 中那些未定义的布局规则

    只要你用 XAML 写代码,我敢打赌你一定用各种方式使(nuè)用(dài)过 Grid.不知你有没有在此过程中看到过 Grid 那些匪夷所思的布局结果呢? 本文将带你来看看 Grid 布局中的 Bu ...

  8. strcasecmp在VS2010中提示未定义标识符

    分析: strcasecmp(*,*)是用来比较字符串,定义在string.h头文件中,但是在windows下即使添加string.h头文件,依然会报错. 解决: 添加 #if defined(_MS ...

  9. javascript中的未定义和未声明

    我们在项目中,经常会定义一些变量(很多时候,定义过多的全局变量),当我们调用这些变量的时候,就会发生各种各样的突发状况. 看一个示例: var a; typeof a; typeof b; 很简单的一 ...

随机推荐

  1. 手动创建DataTable并绑定gridview

    原文发布时间为:2008-08-04 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...

  2. linux-3.2.36内核启动2-setup_arch中的内存初始化1(arm平台 分析高端内存和初始化memblock)【转】

    转自:http://blog.csdn.net/tommy_wxie/article/details/17093307 上一篇微博留下了这几个函数,现在我们来分析它们         sanity_c ...

  3. LeetCode OJ--Merge Sorted Array *

    http://oj.leetcode.com/problems/merge-sorted-array/ 两个有序数组A和B的归并排序,将结果存到A中.因为已知两数组长度且A的数组足够大,所以倒着处理, ...

  4. 提高速度 history 的利用

    history的介绍history是shell的内置命令,其内容在系统默认的shell的man手册中.history是显示在终端输入并执行的过命令,系统默认保留1000条.[root@localhos ...

  5. pt-pmp :pt toolkit

    http://www.cnblogs.com/ivictor/p/6012183.html

  6. 从顺序随机I/O原理来讨论MYSQL MRR NLJ BNL BKA

    http://blog.itpub.net/7728585/viewspace-2129502/

  7. [IOS笔记] - 动画animation

    //移动 - (IBAction)translation:(id)sender { CABasicAnimation *traslation = [CABasicAnimation animation ...

  8. 【Navicat preminm】64位的Navicat preminm注册

    百度云盘 技术-->Navicat preminm+破解

  9. 投资人王刚口述:滴滴如何用八十万成为百亿美金公司? zz

    作者|李好福布斯杂志中文版采编 阿里巴巴前高管.滴滴打车天使投资人王刚近日在杭州接受了<福布斯>独家专访,讲述了集齐“阿里的人.百度的技术.腾讯的钱”的滴滴如何从八十万启动资金,在三年内成 ...

  10. Caused by: java.io.FileNotFoundException: rmi_keystore.jks (没有那个文件或目录)

    解决方法:修改jmeter.properites: server.rmi.ssl.disable=true,关闭ssl功能 参考: https://blog.csdn.net/nielinqi520/ ...