lua语言快速入门

1. Lua快速入门

1.1 数据类型

Lua 中的数据类型不多,可以通过 type 函数来返回一个值的类型

print(type(print))
print(type(true))
print(type(360.0))
print(type({
    
    }))
print(type(nil))
--function
--boolean
--number
--table
--nil

1.1.2 字符串

在 Lua 中,字符串是不可变的值,如果要修改某个字符串,就等于创建了一个新的字符串。这种做法显然有利有弊:好处是即使同一个字符串出现了很多次,在内存中也只有一份;但劣势也很明显,如果想修改、拼接字符串,会额外地创建很多不必要的字符串。

下面这段代码来说明这个弊端。把 1 到 10 这些数字当作字符串拼接起来,在 Lua 中,使用两个点号来表示字符串的相加

local s = ""
for i = 1, 10 do
    s = s .. tostring(i)
end print(s)

这里循环了 10 次,但只有最后一次是想要的,而中间新建的 9 个字符串都是无用的。它们不仅占用了额外的空间,也消耗了不必要的 CPU 运算。

另外,在 Lua 中,有三种方式可以表达一个字符串:单引号、双引号,以及长括号([[]])。
长括号中的字符串不会做任何的转义处理,如果字符串中包括了长括号本身,则在长括号中间增加一个或者多个 = 符号

print([[string has \n and \r]])
-- string has \n and \r
print([=[string has a [[]].]=])
-- string has a [[]].

1.1.3 布尔值

在 Lua 中,只有 nil 和 false 为假,其他都为真,包括 0 和空字符串也为真。

local a = 0
if a then
    print("true")
end
a = ""
if a then
    print("true")
end

这种判断方式和很多常见的开发语言并不一致,所以,为了避免在这种问题上出错,可以显式地写明比较的对象,比如下面这样:

local a = 0
if a == false then
    print("true")
end

1.1.4 数字

Lua 的 number 类型,是用双精度浮点数来实现的。值得一提的是,LuaJIT 支持 dual-number(双数)模式,也就是说, LuaJIT 会根据上下文来用整型来存储整数,而用双精度浮点数来存放浮点数。

此外,LuaJIT 还支持长长整型的大整数,比如下面的例子
resty(OpenResty命令)


$ resty -e 'print(9223372036854775807LL - 1)'
9223372036854775806LL

1.1.5 函数

可以把函数存放在一个变量中,也可以当作另外一个函数的入参和出参
比如,下面两个函数的声明是完全等价的:

function foo()
 end

foo = function ()
 end

1.1.6 table

table 是 Lua 中唯一的数据结构

local color = {
    
     first = "red" }
print(color["first"])
--red

1.1.7 空值

在 Lua 中,空值就是 nil。如果定义了一个变量,但没有赋值,它的默认值就是 nil:

local a
print(type(a))
--nil

1.2 常用标准库

Lua 比较小巧,内置的标准库并不多

1.2.1 string 库

字符串操作是最常用到的,也是坑最多的地方。Lua 的正则独树一帜,不符合 PCRE 的规范。

其中 string.byte(s [, i [, j ]]),是比较常用到的一个 string 库函数,它返回字符 s[i]、s[i + 1]、s[i + 2]、······、s[j] 所对应的 ASCII 码。i 的默认值为 1,即第一个字节,j 的默认值为 i。

print(string.byte("abc", 1, 3))
print(string.byte("abc", 3)) -- 缺少第三个参数,第三个参数默认与第二个相同,此时为 3
print(string.byte("abc"))    -- 缺少第二个和第三个参数,此时这两个参数都默认为 1
--97 98 99
--99
--97

1.2.2 table 库

table.concat一般用在字符串拼接的场景下,比如下面这个例子。它可以避免生成很多无用的字符串。

local a = {
    
    "A", "b", "C"}
print(table.concat(a))

1.2.3 math 库

Lua math 库由一组标准的数学函数构成。数学库的引入,既丰富了 Lua 编程语言的功能,同时也方便了程序的编写。

比如下面的这段代码,它可以在指定的范围内,随机地生成两个数字。

math.randomseed(os.time())
print(math.random())
print(math.random(100))

1.3 虚变量

Lua 提供了一个虚变量(dummy variable)的概念,以一个下划线来命名,用来表示丢弃不需要的数值,仅仅起到占位的作用。

下面以 string.find 这个标准库函数为例,来看虚变量的用法。这个标准库函数会返回两个值,分别代表开始和结束的下标。

如果只需要获取开始的下标,那么很简单,只声明一个变量来接收 string.find 的返回值即可:

local start = string.find("hello", "he") 
print(start)
--1

但如果只想获取结束的下标,那就必须使用虚变量了:

local _, end_pos = string.find("hello", "he")
print(end_pos)
--2

除了在返回值里使用,虚变量还经常用于循环中,比如下面这个例子:

for _, v in ipairs({
    
     4, 5, 6 }) do
    print(v)
end
--4
--5
--6

2. Lua 语言比较特别的几个地方

2.1 Lua 的下标从 1 开始

t={
    
    100};
print(type(t[0]))
print(type(t[1]))
--nil
--number

下标0打印出来是空值

2.2 使用 … 来拼接字符串

和大部分语言使用 + 不同,Lua 中使用两个点号来拼接字符串:

print('hello' .. ', world')

2.3 只有 table 这一种数据结构

Lua 中只有一种数据结构,那就是 table,它里面可以包括数组和哈希表:

local color = {
    
    first = "red", "blue", third = "green", "yellow"}
print(color["first"])                 --> output: red
print(color[1])                         --> output: blue
print(color["third"])                --> output: green
print(color[2])                         --> output: yellow
print(color[3])                         --> output: nil

如果不显式地用_键值对_的方式赋值,table 就会默认用数字作为下标,从 1 开始。所以 color[1] 就是 blue。

另外,想在 table 中获取到正确长度,也是一件不容易的事情

local t1 = {
    
     1, 2, 3 }
print("Test1 " .. table.getn(t1))

local t2 = {
    
     1, a = 2, 3 }
print("Test2 " .. table.getn(t2))

local t3 = {
    
     1, nil }
print("Test3 " .. table.getn(t3))
--Test1 3
--Test2 2
--Test3 1

想要在 Lua 中获取 table 长度,必须注意到,只有在 table 是 ‘序列’ 的时候,才能返回正确的值。

那什么是序列呢?首先序列是数组(array)的子集,也就是说,table 中的元素都可以用正整数下标访问到,不存在键值对的情况。对应到上面的代码中,除了 t2 外,其他的 table 都是 array。

其次,序列中不包含空洞(hole),即 nil。综合这两点来看,上面的 table 中, t1 是一个序列,而 t3 是 array,却不是序列(sequence)。

2.4 默认是全局变量

在 Lua 中声明变量时,前面都要加上 local

local s = 'hello'

这是因为在 Lua 中,变量默认是全局的,会被放到名为 _G 的 table 中。不加 local 的变量会在全局表中查找,这是昂贵的操作。如果再加上一些变量名的拼写错误,就会造成难以定位的 bug。

所以,强烈建议总是使用 local 来声明变量,即使在 require module 的时候也是一样:

-- Recommended 
local xxx = require('xxx')
-- Avoid
require('xxx')

猜你喜欢

转载自blog.csdn.net/qq_33873431/article/details/112213724
今日推荐