OpenRestyの真の値と偽の値とピット
Luaの真の値と偽の値を再確認します:nilとfalseが偽であることを除いて、その他の値はすべて真です.「その他の値」という概念には、0、空の文字列、空のテーブルなどが含まれます.Luaでは、通常、論理オペレータとして
OK、復習はこれで終わり、このいくつかのルールから派生した様々な穴を見てみましょう.
最初のピット
Luaコードでは、パラメータにデフォルト値を設定する慣用として、
ここは今日私たちが出会った最初の穴です.前に言ったように、
nilとfalseを除いて
nil以外にfalseもありますよ!
コードを書くときは、前にデフォルト値を設定した文をついでにコピーします.あるいは業務の変動で、元の入参がブールタイプになり、一気にこの穴に落ちたのかもしれません.だからこの慣用法は、書くのに便利だが、注意して、お菓子をたくさん残さなければならない.
2番目のピット
前の最初の穴を見て、一部の仲間は穴を飛び越える方法を考えているかもしれません.
Luaには三元オペレータがありません!Luaには三元オペレータがありません!Luaには三元オペレータがありません!
大事なことを3回言う!Luaコードでは様々な3元オペレータのシミュレーションを見たことがあるかもしれませんが、それらはシミュレーションです.シミュレーションである以上、偽物にすぎないが、偽物で本物を乱す高模倣品があるにすぎない.
bの値が偽である場合、
上記の例では、xxは伝達された変数なので、caseを走るだけで穴であることがわかります.しかし、bの位置が関数の戻り値であれば?例えば
本明細書がこれで終了すると、その名前は
3番目のピット
Lua内のnilはプレースホルダとして機能しないため,redisキー対応値が空のようなデータの空きを表すためにOpenRestyは
ngx.nullはnull字を持っていますが、nilに等しいわけではありません.先頭のルール(他の値は真)に基づいてngx.nullのブール値は真です.ブール値は本当で、空の定数を表しています.正直に言うと、私はまだ他のプログラミング環境で見たことがありません.これはまた潜在的な穴です.考えているうちに、うっかりして偽の値として考えてしまうからです.例えば、redisから特定のキーを取得し、存在しない場合は関数Aを呼び出す.
このような場合、下位層で外部データサービスと付き合うコードに職を止め、ngxを適切に処理することを確保する必要がある.null .具体的にどのように処理するかについては、ngx.nullをnilに変換するか、ビジネス関連のデフォルト値に変更するかは、具体的なビジネスロジックによって決まります.
4番目の穴
これまでngxを見てきましたnullという特立独行の空の値です.OpenRestyにはもう一つの空の値があります.LuaJIT FFIのcdata:NULLに由来します.ngxのようにnullはuserdataカテゴリ内のNULLであり、cdata:NULLはcdataカテゴリ内のNULLである.FFIインタフェースを介してC関数を呼び出すと、この関数はNULLポインタを返し、Luaコードから見ればcdata:NULL値を受信します.当然のことながら、このとき返される値はnilであるべきだと思うかもしれませんが、Luaの中のnilが対応しているのは、Cの中のNULLではないでしょうか.しかし、天が気に入らないので、この時帰ってきたのはcdata:NULLで、変な子です.
どうして変な子だと言ったの?nilと等しいのでngx.nullはnilに等しくありません.しかし、nilと等しいということは、nilを置き換えることができるという意味ではありません.cdata:NULLは、最初に述べたルールに従います.ブール値が真であることを意味します.もう一つのブール値は本当で、空の定数を表します!そして今回はもっと変で、この空定数はnilと等しい!
次の例のコードを見てみましょう.
どのように処理しますか?多くの場合、FFI呼び出しが返すのが
次のピットのように、下部でCインタフェースと付き合うときにcdata:NULLを除去し、拡散させないでください.「災い」コードの他の部分です.
and
およびor
が使用される.例えば、true and false
はfalse
を返し、false or true
はtrue
を返します.OK、復習はこれで終わり、このいくつかのルールから派生した様々な穴を見てみましょう.
最初のピット
Luaコードでは、パラメータにデフォルト値を設定する慣用として、
xx = xx or value
の文が一般的に見られます.xxパラメータに値が指定されていない場合、その値はnilであり、文はvalueに値を与えます.ここは今日私たちが出会った最初の穴です.前に言ったように、
nilとfalseを除いて
nil以外にfalseもありますよ!
コードを書くときは、前にデフォルト値を設定した文をついでにコピーします.あるいは業務の変動で、元の入参がブールタイプになり、一気にこの穴に落ちたのかもしれません.だからこの慣用法は、書くのに便利だが、注意して、お菓子をたくさん残さなければならない.
2番目のピット
前の最初の穴を見て、一部の仲間は穴を飛び越える方法を考えているかもしれません.
xx = (xx == nil) and xx or value
に変更します.実際に走ってみると、この文もxxがfalseのcaseには及ばないことがわかります.これが2番目の穴です.Luaには三元オペレータがありません!Luaには三元オペレータがありません!Luaには三元オペレータがありません!
大事なことを3回言う!Luaコードでは様々な3元オペレータのシミュレーションを見たことがあるかもしれませんが、それらはシミュレーションです.シミュレーションである以上、偽物にすぎないが、偽物で本物を乱す高模倣品があるにすぎない.
a and b or c
モードは、これらの高模倣品の一員です.このモードは、a and b
からxを得、x or c
を実行して最終結果yを得る2つの式を含む.ほとんどの場合、3元オペレータのように表現されます.しかし、残念ながらそうではありません.bの値が偽である場合、
a and b
の実行結果は一定である.xが一定である場合、x or c
の実行結果はcに一定である.したがって、bの値が偽である限り、最終結果はcに保たれる.上記の例では、xxは伝達された変数なので、caseを走るだけで穴であることがわかります.しかし、bの位置が関数の戻り値であれば?例えば
expr and func1() or func2()
の形式では、func 1がたまに偽値を返すだけで、1つのタイミング爆弾が埋め込まれている.やはり最初の穴のような結論で、慣用法は使えますが、お菓子をたくさん残します.本明細書がこれで終了すると、その名前は
Lua
であるべきである.しかし、実際のタイトルはOpenResty
なので、OpenResty専用のピットについて説明します.3番目のピット
Lua内のnilはプレースホルダとして機能しないため,redisキー対応値が空のようなデータの空きを表すためにOpenRestyは
ngx.null
という定数を導入した.ngx.null
はNULLのuserdataです.$ resty -e 'print(tostring(ngx.null))'
userdata: NULL
ngx.nullはnull字を持っていますが、nilに等しいわけではありません.先頭のルール(他の値は真)に基づいてngx.nullのブール値は真です.ブール値は本当で、空の定数を表しています.正直に言うと、私はまだ他のプログラミング環境で見たことがありません.これはまた潜在的な穴です.考えているうちに、うっかりして偽の値として考えてしまうからです.例えば、redisから特定のキーを取得し、存在しない場合は関数Aを呼び出す.
ngx.null
の特殊性が一時半で思い出せない場合は、戻り値が真(またはnil)かどうかを直接判断して穴に落ちてしまう可能性があります.特に、下位論理がngxをnullが包装されていて、上層部が呼び出した人はnilとvalueのほかにngxがあるとは思わなかったかもしれません.nullの存在!local res, err = redis.get('key1')
if not res then
...
end
-- , key1 …… 500 Internal Server Error!
-- res = res + 1
--
if res ~= ngx.null then
res = res + 1
このような場合、下位層で外部データサービスと付き合うコードに職を止め、ngxを適切に処理することを確保する必要がある.null .具体的にどのように処理するかについては、ngx.nullをnilに変換するか、ビジネス関連のデフォルト値に変更するかは、具体的なビジネスロジックによって決まります.
4番目の穴
これまでngxを見てきましたnullという特立独行の空の値です.OpenRestyにはもう一つの空の値があります.LuaJIT FFIのcdata:NULLに由来します.ngxのようにnullはuserdataカテゴリ内のNULLであり、cdata:NULLはcdataカテゴリ内のNULLである.FFIインタフェースを介してC関数を呼び出すと、この関数はNULLポインタを返し、Luaコードから見ればcdata:NULL値を受信します.当然のことながら、このとき返される値はnilであるべきだと思うかもしれませんが、Luaの中のnilが対応しているのは、Cの中のNULLではないでしょうか.しかし、天が気に入らないので、この時帰ってきたのはcdata:NULLで、変な子です.
どうして変な子だと言ったの?nilと等しいのでngx.nullはnilに等しくありません.しかし、nilと等しいということは、nilを置き換えることができるという意味ではありません.cdata:NULLは、最初に述べたルールに従います.ブール値が真であることを意味します.もう一つのブール値は本当で、空の定数を表します!そして今回はもっと変で、この空定数はnilと等しい!
次の例のコードを見てみましょう.
#!/usr/bin/env luajit
local ffi = require "ffi"
local cdata_null = ffi.new("void*", nil)
print(tostring(cdata_null))
if cdata_null == nil then
print('cdata:NULL is equal to nil')
end
if cdata_null then
print('...but it is not nil!')
end
どのように処理しますか?多くの場合、FFI呼び出しが返すのが
cdata:NULL
かどうかを判断すれば十分である.cdata:NULL
とnil
が等しいことを利用することができます.#!/usr/bin/env luajit
local ffi = require "ffi"
local cdata_null = ffi.new("void*", nil)
if cdata_null == nil then
print('cdata:NULL found')
end
次のピットのように、下部でCインタフェースと付き合うときにcdata:NULLを除去し、拡散させないでください.「災い」コードの他の部分です.