溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

golua虛擬機的使用分析

發(fā)布時間:2021-11-10 18:54:00 來源:億速云 閱讀:135 作者:柒染 欄目:云計算

golua虛擬機的使用分析,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

前言

之前一直想把openflow這樣的分布式流程系統(tǒng)做起來,但是時間和應(yīng)用場景的問題所以都是做了一個半拉子工程,而且之前想的也有點簡單了,認(rèn)為只要有同學(xué)愿意,在開發(fā)上應(yīng)該沒問題,但是最終還是出現(xiàn)了項目管理和開發(fā)能力的問題,最終擱淺了。但是我想做一個分布式流程調(diào)度系統(tǒng)的想法一直沒有斷,其實在公司內(nèi)和另外一個同學(xué)做過一個flow系統(tǒng),也在線上使用了,直到現(xiàn)在還在使用。前一段時間就想把這個系統(tǒng)再優(yōu)化梳理一下,目標(biāo)是做一個小巧的開源可用版本。經(jīng)過一段時間的梳理目前已經(jīng)初步完成了,后臺+前端代碼的重新梳理也已經(jīng)完成了。

lua虛擬機的使用

而今天主要想寫的是其中使用到的一個技術(shù)點:lua。內(nèi)部版本我們使用的是golang開發(fā),但是在執(zhí)行中為了保證流程之間不會互相影響,我們使用lua虛擬機技術(shù);讓每個流程在執(zhí)行的時候在一個獨立的lua虛擬機中執(zhí)行。內(nèi)部版本使用golua這個組件,但是這個組件有個問題,它其實是一個cgo的版本,就是它其實上是調(diào)用本地lua庫來執(zhí)行,所在在編譯部署和執(zhí)行上都有一定的效率問題。

所以在新開發(fā)的版本上我想使用其它的方式,在研究了一段時間后決定使用gopher-lua這個組件,這個是使用golang重寫的支持Lua5.1的虛擬機,在執(zhí)行上可以直接golang無縫結(jié)合,有非常好的go的api接口,在使用上也流暢很多,在實現(xiàn)思路上也采用golang的一些思路,和golang結(jié)合更好。也通過這次學(xué)習(xí)了一把lua,才發(fā)現(xiàn)這個技術(shù)確實很牛,據(jù)統(tǒng)計lua的c實現(xiàn)代碼才1w行左右,但是執(zhí)行非常高效,而且lua的預(yù)留關(guān)鍵字也非常少??梢哉f是一個非常簡潔又高效的語言。

gopher-lua的一些特點

在我這個flow項目非常合適,所以用gopher-lua替換了golua,因為gopher-lua的api和類型支持比golua要好很多,所以在替換后精簡了不少代碼。下面就介紹一下項目中使用到的一些關(guān)鍵點。

lua虛擬機的創(chuàng)建使用

在使用上api非常簡單,主要有以下幾步:

  1. 引入gopher-lua

  2. 創(chuàng)建虛擬機

  3. 使用虛擬機執(zhí)行l(wèi)ua語句或lua腳本文件

  4. 關(guān)閉虛擬機

package mainimport lua "github.com/yuin/gopher-lua" // 1.引入gopher-luafunc main() {
	L := lua.NewState() // 2.創(chuàng)建一個lua解釋器實例defer L.Close()    // 4.關(guān)閉虛擬機if err := L.DoString(`print("hello")`); err != nil { // 3.用創(chuàng)建的虛擬機來執(zhí)行l(wèi)ua語句   
     // if err := L.DoFile("hello.lua"); err != nil { // 3.用創(chuàng)建的虛擬機來執(zhí)行l(wèi)ua腳本文件panic(err)
	}
}

api在使用上還是非常簡單的。其它關(guān)于基本數(shù)據(jù)類型的這里就不多介紹了,在其github站點上有非常詳細的介紹。

下面將主要介紹2個在flow項目中用到的非常有用的功能點。

go中調(diào)用lua函數(shù)

用golang寫的服務(wù),如果我們要使用lua腳本中定義的函數(shù)怎么辦呢?在gopher-lua提供了響應(yīng)的方法,在其站點也有非常好的例子來說明:

  1. 首先用DoFile方法來加載lua腳本,在腳本中定義需要lua函數(shù)

  2. 其次使用CallByParam函數(shù)進行調(diào)用

L := lua.NewState()defer L.Close()if err := L.DoFile("double.lua"); err != nil {    panic(err)
}if err := L.CallByParam(lua.P{
    Fn: L.GetGlobal("double"), 	  // 獲取double這個函數(shù)的引用
    NRet: 1,					// 指定返回值數(shù)量
    Protect: true,                // 如果出現(xiàn)異常,是panic還是返回err
    }, lua.LNumber(10)); err != nil { // 傳遞輸入?yún)?shù):10
    panic(err)
}
ret := L.Get(-1) // 獲取返回結(jié)果值L.Pop(1)  // 從堆棧中扔掉返回結(jié)果

GopherLua的函數(shù)調(diào)用是通過堆棧來進行的,調(diào)用前把需要傳遞給函數(shù)的參數(shù)壓到棧里,函數(shù)執(zhí)行完成之后再將結(jié)果放入堆棧中,調(diào)用方通過在堆棧頂部拿函數(shù)執(zhí)行結(jié)果。

lua腳本中調(diào)用go函數(shù)

go調(diào)用lua函數(shù)在flow項目中用的相對較少,用的較多的是下面一種:lua腳本中調(diào)用go函數(shù);因為很多復(fù)雜操作其實用lua來做還是有點復(fù)雜和不安全,尤其有些公共操作或者復(fù)雜的db操作。所以好的做法是在go中把函數(shù)封裝好,再在外部寫lua腳本,執(zhí)行的時候可以調(diào)用go函數(shù),這樣既可以滿足lua腳本的靈活性,也極大的擴展了lua的能力和減低了編寫復(fù)雜度。

先看看其基本使用方法,也是通過官網(wǎng)的例子來說明。

func Double(L *lua.LState) int {
    lv := L.ToInt(1)             // 獲取七個參數(shù)
    L.Push(lua.LNumber(lv * 2))  // 把計算結(jié)果壓棧
    return 1                     // 返回計算返回參數(shù)的個數(shù)}func main() {
    L := lua.NewState()    defer L.Close()
    L.SetGlobal("double", L.NewFunction(Double)) // 注冊函數(shù)}

首先再gopher-lua中有一個類型lua.LGFunction ,這個類型就是一個函數(shù)類型,它固定了函數(shù)的入?yún)⒑统鰠?,入?yún)⒕褪莑ua.LState的一個引用,返回值就是一個int。如下面的定義,如果需要跟多的參數(shù)就需要使用堆?;蛘邔ua.LState擴展成員的方式。在執(zhí)行完成之后也是通過堆?;蛘邔ua.LState擴展成員的方式把返回值傳遞出去。

函數(shù)的注冊有多種方式,上面是一種方式,另外我從網(wǎng)上還看到一種方式,就是使用lua的table的方式。

	myfuns := L.NewTable()
	L.SetGlobal("myfuns", myfuns)
	// 注冊函數(shù)
	L.SetField(myfuns, "gofun1", L.NewFunction(gofun1))
	....
	// 調(diào)用方式
	err := L.DoString(`
		test = myfuns:gofun1("test")
	`)

這里面不方便的一點就是參數(shù)的傳遞和獲取不是很直觀,很多時候需要二次分裝調(diào)用函數(shù)。這一點有點不方便。其它還好。

GopherLua可以創(chuàng)建一個非常干凈的Lua解釋器實例,不加載任何系統(tǒng)模塊。然后由程序員自己提供的模塊注冊進去,給內(nèi)嵌腳本提供一個安全的沙箱運行環(huán)境。

關(guān)于golua虛擬機的使用分析問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI