21
在golang中使用lua脚本
source link: https://studygolang.com/articles/19703?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
lua基础
注释:
-- this is a comment
声明全局变量:
x = 123
声明本地变量:
local y = 456
方法声明:
function hello_world() return "Hello World" end
迭代:
for i = 1, 10 do print(i) end
条件:
if x == 123 then print("x is the magic number") else print("I have no idea what x is") end
字符串连接:
print("Hello" .. " World")
作为数组使用一个table — 数组的索引从1开始:
data_types = {1.0, 123, "redis", true, false, hello_world} print(data_types[3]) -- the output is "redis"
作为hash使用一个table:
languages = {lua = 1993, javascript = 1995, python = 1991, ruby =1995} print("Lua was created in " .. languages["lua"]) print("JavaScript was created in " .. languages.javascript)
redis脚本执行是一种原子操作,所以在执行期间redis服务会被阻塞。默认脚本操作会有5秒的执行时间
当一个lua脚本执行超时不会自动停止,它会开始对每一个命令回复一个busy状态,表明脚本正在运行。使用命令 SCRIPT KILL
或者 SHUTDOWN NOSAVE
终止脚本执行才能使redis服务回到正常状态
举个栗子
package main import ( "fmt" "github.com/go-redis/redis" ) var Client *redis.Client func init() { Client = redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB }) } //noinspection GoInvalidCompositeLiteral func main() { Client.FlushAll() Client.Set("foo", "bar" , 0) var luaScript = redis.NewScript(`return redis.call("GET" , KEYS[1])`) n , err := luaScript.Run(Client , []string{"foo"}).Result() if err != nil { panic(err) } fmt.Println(n , err) }
另一个栗子
package main import ( "fmt" "github.com/go-redis/redis" ) var Client *redis.Client func init() { Client = redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB }) } //noinspection GoInvalidCompositeLiteral func main() { Client.FlushAll() foo := []redis.Z{ { 1732, "George Washington", }, { 1809, "Abraham Lincoln", }, { 1858, "Theodore Roosevelt", }, } Client.ZAdd("presidents", foo...) var luaScript = redis.NewScript(` local elements = redis.call("ZRANGE" , KEYS[1] , 0 , 0) redis.call("ZREM" , KEYS[1] , elements[1]) return elements[1] `) n , err := luaScript.Run(Client , []string{"presidents"} , 1).Result() if err != nil { panic(err) } fmt.Println(n , err) }
使用evalsha来操作lua
当执行脚本多次的时候,可以使用 SCRIPT LOAD
和 EVALSHA
代替 EVAL
有可能节省带宽。命令 SCRIPT LOAD
缓存一个lua脚本,同时返回一个sha1的标识符。命令 EVALSHA
基于sha1的标识符执行脚本,通过 SCRIPT LOAD
返回。使用 EVALSHA
只有标识符通过网络传输,而不是一个lua代码块
继续举个栗子
package main import ( "fmt" "github.com/go-redis/redis" ) var Client *redis.Client func init() { Client = redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB }) } //noinspection GoInvalidCompositeLiteral func main() { Client.FlushAll() Client.Set("foo" , "bar" , -1) var luaScript = `return redis.call("INFO")` result ,err := Client.ScriptLoad(luaScript).Result() //返回的脚本会产生一个sha1哈希值,下次用的时候可以直接使用这个值,类似于 if err != nil { panic(err) } foo :=Client.EvalSha(result ,[]string{}) fmt.Println(foo.Val()) }
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK