您的位置 首页 golang

用Golang运行JavaScript

用Golang运行JavaScript

C++太麻烦(难)了,想要盘弄一下 V8 实在是有些费劲,但是Golang社区出了几个Javascript引擎,要尝试在别的语言中如何集成Javascript,是个不错的选择。以下选了 github.com/dop251/goja 来做例子。

Hello world

照着仓库的Readme,来一个:

package main

import (
 "fmt"
 js "github.com/dop251/goja"
)

func main() {
  vm  := js.New() // 创建engine实例
 r, _ := vm.RunString(`
 1 + 1
 `) // 执行javascript代码
 v, _ : = r.Export().(int64) // 将执行的结果转换为Golang对应的类型
 fmt.Println(r)
} 

这个例子展示了最基本的能力,给定一段Javascript的代码文本,它能执行得到一个结果,并且能得到执行结果的宿主语言的表示形式。

交互

Javascript和Golang之间的交互分成两个方面:Golang向Javascript引擎中注入一些上下文,例如注册一些全局函数供Javascript使用,创建一个对象等;Golang从Javascript引擎中读取一些上下文,例如一个计算过程的计算结果。先看第一类。

常用的手段是,通过Runtime类型提供的Set方法在全局注册一个变量,例如

...
rts := js.New()
rts.Set("x", 2)
rts.RunString(`x+x`) // 4
... 

此处Set的方法签名是 func (r *Runtime) Set(name string, value interface{}) ,对于基本类型,不需要额外的包装,就可以自动转换,但是当需要传递一个复杂对象时,需要用 NewObject 包装一下:

rts := js.New()
o := rts.NewObject()
o.Set("x", 2)
rts.Set("o", o)
rts.RunString(`o.x+o.x`) // 4 

切换到Golang的视角,是个很自然的过程,想要创建一个对象,需要在Golang中先创建一个对应的表述,然后在Javascript中才能使用。对于更复杂的对象,嵌套就好了。

定义函数则有所不同,不同之处在于Javascript中的函数在Golang中的表示和其它类型的值不太一样,Golang中表式Javascript中的函数的签名为: func (js.FunctionCall) js.Value , js.FunctionCall 中包含了调用函数的上下文信息,基于此我们可以尝试给Javascript增加一个 console.log 的能力:

...
func log(call js.FunctionCall) js.Value {
 str := call.Argument(0)
 fmt.Print(str.String())
 return str
}
...
rts := js.New()
console := rts.NewObject()
console.Set("log", log)
rts.Set("console", console)
rts.RunString(`console.log('hello world')`) // hello world 

相较于向Javascript引擎中注入一些信息,从中读取信息则比较简单,前面的hello world中展示了一种方法,执行一段Javascript代码,然后得到一个结果。但是这种方法不够灵活,如果想要精确的得到某个上下文,变量的值,就不那么方便。为此, goja 提供了Get方法,Runtime类型的Get方法可以从Runtime中读取某个变量的信息,Object类型的Get方法则可以从对象中读取某个字段的值。签名如下: func (r *Runtime) Get(name string) Value , func (o *Object) Get(name string) Value 。但是得到的值的类型都是Value类型,想要转换成对应的类型,需要通过一些方法来转换,这里就不再赘述,有兴趣可以去看它的文档。

一个复杂些的例子

goja值提供了基本的解析执行Javascript代码的能力,但是我们常见的宿主提供的能力,需要在使用的过程中自己去补充。下面就基于上面的技巧,提供一个简单的 require 加载本地Javascript代码的能力。

通过require加载一段Commjs格式Javascript代码,直观的流程:根据文件名,读取文本,组装成一个立即执行函数,执行,然后返回module对象,但是中间可以做一些小优化,比如已经被加载过的代码, 就不重新加载,执行,只是返回就好了。大概的实现如下:

package core

import (
 "io/ioutil"
 "path/filepath"

 js "github.com/dop251/goja"
)

func moduleTemplate(c string) string {
 return "(function(module, exports) {" + c + "n})"
}

func createModule(c *Core) *js.Object {
 r := c.GetRts()
 m := r.NewObject()
 e := r.NewObject()
 m.Set("exports", e)

 return m
}

func compileModule(p string) *js.Program {
 code, _ := ioutil.ReadFile(p)
 text := moduleTemplate(string(code))
 prg, _ := js.Compile(p, text, false)

 return prg
}

func loadModule(c *Core, p string) js.Value {
 p = filepath.Clean(p)
 pkg := c.Pkg[p]
 if pkg != nil {
 return pkg
 }

 prg := compileModule(p)

 r := c.GetRts()
 f, _ := r.RunProgram(prg)
 g, _ := js.AssertFunction(f)

 m := createModule(c)
 jsExports := m.Get("exports")
 g(jsExports, m, jsExports)

 return m.Get("exports")
} 

要想让引擎能使用这个能力,就需要将require这个函数注册到Runtime中,

// RegisterLoader register a simple commonjs style loader to runtime
func RegisterLoader(c *Core) {
 r := c.GetRts()

 r.Set("require", func(call js.FunctionCall) js.Value {
 p := call.Argument(0).String()
 return loadModule(c, p)
 })
} 

完整的例子有兴趣可看 github.com/81120/gode

写在后面

之前一直分不清Javascript引擎和Javascript执行环境的界限,通过这个例子,有了一个很具体的认识。而且,对Node本身的结构也有了一个更清楚的认知。在一些场景下,需要将一些语言嵌入到另一个语言中实现一些更灵活的功能和解耦,例如 nginx 中的 lua ,游戏引擎中的lua,mongodb shell中的Javascipt,甚至nginx官方头提供了一个阉割版本的Javascript实现作为配置的DSL。那么在这种需要嵌入DSL的场景下,嵌入一个成熟语言的执行引擎比自己实现一个DSL要简单方便得多。而且,各种场景下,对语言本身的要求也不尽相同,例如边缘计算场景,嵌入式下,可以用Javascript来开发,但是是不是需要一个完整的V8呢?对环境和性能有特殊要求的场景下,限制DSL,提供必要的宿主语言扩展也是个不错的思路吧。

原文链接:

文章来源:智云一二三科技

文章标题:用Golang运行JavaScript

文章地址:https://www.zhihuclub.com/99452.shtml

关于作者: 智云科技

热门文章

评论已关闭

37条评论

  1. nelfinavir will increase the level or effect of tadalafil by affecting hepatic intestinal enzyme CYP3A4 metabolism or how to strategically outmaneuver a strong, entrenched, competitor

  2. Your doctor or nurse practitioner needs to know about your general health and how excessive sweating affects you

  3. In lieu of a quantitative analysis, this section provides a qualitative discussion of how the various strategies would differ across geographic settings.

  4. Author Contributions S Treatment of mice bearing established MCF 7 tumors with estrogen withdrawal removal of estrogen pellet resulted in cessation of tumor growth, but not in tumor regression

  5. Common chemo drugs used include anthracyclines, taxanes, capecitabine, gemcitabine, eribulin, and others

  6. 6 mm, 5 Ојm; Phenomenex Inc Importantly, inflammation alters the diversity in your microbiome which sets off a vicious cycle

  7. A healthy 70 year old woman has participated in a longitudinal study of the effects of aging on performance during pulmonary function tests for the past 50 years

  8. Demographic data of carriers were collected Self administration of a multiquestion questionnaire called the Functional Assessment of Cancer Therapy Breast FACT B

  9. The sentencing judge said his hands were tied when he ordered as punishment two decades behind bars

  10. net is an approved supplier of Dragon Pharma products, it can be verified online here dragon pharma A suitable volume of PBS with DNase final concentration, 0

  11. com 20 E2 AD 90 20Viagra 20Fara 20Prescriptie 20Medicala 20 20Viagra 20Einzeln 20Kaufen viagra fara prescriptie medicala I m here, I ll remain here and I m not giving up and we will all continue together this battle for democracy and freedom so that citizens aren t afraid of finding themselves in prison without having done anything wrong, he declared

  12. Monitor Closely 1 tazemetostat will decrease the level or effect of escitalopram by affecting hepatic intestinal enzyme CYP3A4 metabolism PMC free article PMC84935 PubMed 10325315

  13. Common symptoms reported while taking isosorbide include Chills Dizziness Headache Lightheadedness Nausea

  14. I think I haven t really put it on top of my agenda to discuss it, but from discussions with the fertility specialist whom I still see once a year and the oncologist, I think it s still an unknown If I have this treatment for five years, so 10 years and at the five year mark, yeah, will I be closer to the natural menopausal age or not based carmakers fits for years, the Ford brandГў

  15. com 20 E2 AD 90 20Cara 20Pemakaian 20Obat 20Kuat 20Viagra 20 20Reseptivapaa 20Viagra reseptivapaa viagra That s when the audience finds out Juliette s solution to losing Rayna as a touring partner inviting Layla to be her opening act

  16. Blurry vision and cloudy vision can also both be symptoms of a serious eye problem, especially if they occur suddenly

  17. Frozen sections 10 Ојm thick were prepared in a cryostat microtome and thaw mounted on Superfrost glass slides Matsunami Glass

  18. Analysis of patient samples and genetically engineered mouse models suggests that it likely develops from preneoplastic ductal lesions, including pancreatic intraepithelial neoplasias PanINs 2

  19. Trade Name Clomiphene Citrate Compound Clomiphene Citrate Strength 50 mg pill Container 50 Pills Manufacturer Genetic Pharmaceuticals

  20. Her work has formed the basis of investigations published by outlets including VICE, NBC and Reveal, and she publishes case studies on her YouTube channel Chemical Heritage Press

  21. 17beta Oestradiol appears to be a specific stimulator of MMP 2 release from human vascular cells

  22. Also used for the prophylactic treatment of all types of hereditary angioedema in males and females

  23. The difference from previous years is testosterone increase food veg that during the Spring Festival this year, there is a brand new rock hard male enhancement film company called Xingchen Films, testosterone increase food veg and Xingchen Films will release a special full CG film called Let Go of the Witch

网站地图