# 从架构层面杜绝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. 我要好offer之 链表大总结

    单链表是一种递归结构,可以将单链表看作特殊的二叉树(我把它叫做一叉树) 单链表的定义: /** * Definition for singly-linked list. * struct ListNo ...

  2. Office 365 切换语言设置

    The steps of changing the language: Click “Setting                         ”>”Office 365 Setting” ...

  3. 应用css3制作loading效果

    参考秒味课堂 代码发出来备忘 html <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

  4. linux 头文件以及库的路径

    原来在编译的时候可以指定执行时去哪里找需要的lib文件,长知识了 本文详细介绍了Linux 下gcc头文件指定方法,以及搜索路径顺序的问题.另外,还总结了,gcc动态链接的方法以及路径指定,同样也讨论 ...

  5. LeetCode OJ--Triangle **

    https://oj.leetcode.com/problems/triangle/ 一个三角形,类似于杨辉三角的形状,求从上到下最小的路径和,但走每一步都得是相邻的. 动态规划,从下到上一层层来. ...

  6. AC日记——狼抓兔子 bzoj 1001

    Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一 ...

  7. WCF的学习之旅

    一.WCF的简单介绍  Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是MS为SOA (S ...

  8. Redis实用监控工具一览

    Redis已经成为web应用开发不可或缺的一个组成部分,在项目中的应用越来越广泛,这篇文章就来讲讲那些关于Redis监控的那点事. vredis-benchmark 1.1 简介 第一个就介绍一下,R ...

  9. Java爬虫系列二:使用HttpClient抓取页面HTML

    爬虫要想爬取需要的信息,首先第一步就要抓取到页面html内容,然后对html进行分析,获取想要的内容.上一篇随笔<Java爬虫系列一:写在开始前>中提到了HttpClient可以抓取页面内 ...

  10. Wannafly挑战赛16

    E(pbds) 题意: 1<=m,n<=5e5 分析: 首先指向关系形成了一个基环外向树森林 实际上我们可以完全不用真正的去移动每个球,而只需要在计数的时候考虑考虑就行了 对于树上的情况, ...