函數 type 能夠返回一個值或一個變量所屬的類型。
print(type("hello world")) -->output:string
print(type(print)) -->output:function
print(type(true)) -->output:boolean
print(type(360.0)) -->output:number
print(type(nil)) -->output:nil
nil(空)
nil 是一種類型,Lua 將 nil 用於表示“無效值”。一個變量在第一次賦值前的默認值是 nil,將nil 賦予給一個全局變量就等同於刪除它。
local num
print(num) -->output:nil
num = 100
print(num) -->output:100
值得一提的是,OpenResty 的 Lua 接口還提供了一種特殊的空值,即 ngx.null ,用來表示不同於 nil 的“空值”。後面在討論 OpenResty 的 Redis 庫的時候,我們還會遇到它。
boolean(布爾)
布爾類型,可選值 true/false;Lua 中 nil 和 false 為“假”,其它所有值均為“真”。比如 0 和空字符串就是“真”;C 或者 Perl 程序員或許會對此感到驚訝。
local a = true
local b = 0
local c = nil
if a then
print("a") -->output:a
else
print("not a") --這個沒有執行
end
if b then
print("b") --這個沒有執行
else
print("not b") -->output:not b
end
if c then
print("c") --這個沒有執行
else
print("not c") -->output:not c
end
number(數字)
Number 類型用於表示實數,和 C/C++ 裡面的 double 類型很類似。可以使用數學函數math.floor(向下取整) 和 math.ceil(向上取整) 進行取整操作。
local order = 3.99
local score = 98.01
print(math.floor(order)) -->output:3
print(math.ceil(score)) -->output:99
一般地,Lua 的 number 類型就是用雙精度浮點數來實現的。值得一提的是,LuaJIT 支持所謂的“dual-number”(雙數) 模式,即 LuaJIT 會根據上下文用整型來存儲整數,而用雙精度浮點數來存放浮點數。
另外,LuaJIT 還支持“長長整型”的大整數(在 x86_64 體系結構上則是 64 位整數) 。例如
print(9223372036854775807LL - 1) -->output:9223372036854775806LL
string(字符串)
Lua 中有三種方式表示字符串:
- 使用一對匹配的單引號。例:'hello'。
- 使用一對匹配的雙引號。例:"abclua"。
- 字符串還可以用一種長括號(即[[ ]]) 括起來的方式定義。
我們把兩個正的方括號(即[[)間插入 n 個等號定義為第 n 級正長括號。就是說,0 級正的長括號寫作 [[ ,一級正的長括號寫作 [=[,如此等等。反的長括號也作類似定義;舉個例子,4 級反的長括號寫作 ]====]。
一個長字符串可以由任何一級的正的長括號開始,而由第一個碰到的同級反的長括號結束。整個詞法分析過程將不受分行限制,不處理任何轉義符,並且忽略掉任何不同級別的長括號。
這種方式描述的字符串可以包含任何東西,當然本級別的反長括號除外。例:[[abc\\nbc]],裡面的 "\\n" 不會被轉義。
另外,Lua 的字符串是不可改變的值,不能像在 c 語言中那樣直接修改字符串的某個字符,而是根據修改要求來創建一個新的字符串。Lua 也不能通過下標來訪問字符串的某個字符。
想了解更多關於字符串的操作,請關注後續String 庫的文章。
local str1 = 'hello world'
local str2 = "hello lua"
local str3 = [["add\\name",'hello']]
local str4 = [=[string have a [[]].]=]
print(str1) -->output:hello world
print(str2) -->output:hello lua
print(str3) -->output:"add\\name",'hello'
print(str4) -->output:string have a [[]].
在 Lua 實現中,Lua 字符串一般都會經歷一個“內化”(intern) 的過程,即兩個完全一樣的Lua 字符串在 Lua 虛擬機中只會存儲一份。每一個 Lua 字符串在創建時都會插入到 Lua 虛擬機內部的一個全局的哈希表中。 這意味著
- 創建相同的 Lua 字符串並不會引入新的動態內存分配操作,所以相對便宜(但仍有全局哈希表查詢的開銷)
- 內容相同的 Lua 字符串不會佔用多份存儲空間
- 已經創建好的 Lua 字符串之間進行相等性比較時是 O(1) 時間度的開銷,而不是通常見到的 O(n)
table (表)
Table 類型實現了一種抽象的“關聯數組”。“關聯數組”是一種具有特殊索引方式的數組,索引通常是字符串(string) 或者 number 類型,但也可以是除 nil 以外的任意類型的值。
local corp = {
web = "www.google.com", --索引為字符串,key = "web",
-- value = "www.google.com"
telephone = "12345678", --索引為字符串
staff = {"Jack", "Scott", "Gary"}, --索引為字符串,值也是一個表
100876, --相當於 [1] = 100876,此時索引為數字
-- key = 1, value = 100876
100191, --相當於 [2] = 100191,此時索引為數字
[10] = 360, --直接把數字索引給出
["city"] = "Beijing" --索引為字符串
}
print(corp.web) -->output:www.google.com
print(corp["telephone"]) -->output:12345678
print(corp[2]) -->output:100191
print(corp["city"]) -->output:"Beijing"
print(corp.staff[1]) -->output:Jack
print(corp[10]) -->output:360
在內部實現上,table 通常實現為一個哈希表、一個數組、或者兩者的混合。具體的實現為何種形式,動態依賴於具體的 table 的鍵分佈特點。
想了解更多關於 table 的操作,請關注後續 Table 庫的文章。
function (函數)
在 Lua 中,函數 也是一種數據類型,函數可以存儲在變量中,可以通過參數傳遞給其他函數,還可以作為其他函數的返回值。
示例
local function foo()
print("in the function")
--dosomething()
local x = 10
local y = 20
return x + y
end
local a = foo --把函數賦給變量
print(a())
--output:
in the function
30
有名函數的定義本質上是匿名函數對變量的賦值。為說明這一點,考慮
function foo()
end
等價於
foo = function ()
end
類似地,
local function foo()
end
等價於
local foo = function ()
end
至此,Lua 基礎數據類型就介紹完了。下一篇將介紹Lua表達式。
後續計劃內容:
Lua入門+高階
Nginx
OpenResty
LuaRestyRedisLibrary
LuaCjsonLibrary
PostgresNginxModule
LuaNginxModule
LuaRestyDNSLibrary
LuaRestyLock
stream_lua_module
balancer_by_lua
OpenResty 與 SSL
測試
Web服務
火焰圖
OpenResty周邊
零碎知識點
閱讀更多 互聯網技能圖譜 的文章