Go be programmed wasm

wasm That webAssemble, which is not a binary format file for a particular platform. Go from 1.11 begun to support wasm, initially by js.NewCallBack () function is registered, 1.12 start into a FuncOf ().

Go wasm need to develop a go file for writing implementation code, compiled into .wasm file; wasm_exec.js need a file, this is provided by Go, Go can be found in the misc subdirectory of the installation directory where it will be directly copied. It implements and WebAssembly module interaction function; another is the need for an HTML file for loading wasm file. Of course, in order to work together, we need to implement a simple HTTP service.

First, write code with Go and compiled into wasm file

  1 package main
  2 
  3 import (
  4     "fmt"
  5     "math/rand"
  6     "strconv"
  7     "syscall/js"
  8     "time"
  9 )
 10 
 11 const (
 12     width  = 400
 13     height = 400
 14 )
 15 
 16 // 生成 0 - 1 的随机数
 17 func getRandomNum() float32 {
 18     rand.New (. rand.NewSource (Time.now () UnixNano ()))
 . 19      n-: = float32 (rand.Intn ( 10000 ))
 20 is      return n-/ 10000.0 
21 is  }
 22 is  
23 is  // generates a 0 - 10 of the random number 
24  FUNC getRandomNum2 () {float32
 25      rand.New (. rand.NewSource (Time.now () UnixNano ()))
 26 is      n-: = float32 (rand.Intn ( 10000 ))
 27      return n-/ 1000.0 
28  }
 29  
30  / / use drawing canvas random FIG. 
31 is  FUNC draw () {
 32      var canvas = js.Value js.
 33         Global().
 34         Get("document").
 35         Call("getElementById", "canvas")
 36 
 37     var context js.Value = canvas.Call("getContext", "2d")
 38 
 39     // reset
 40     canvas.Set("height", height)
 41     canvas.Set("width", width)
42 is      context.Call ( " the clearRect " , 0 , 0 , width, height)
 43 is  
44 is      // random straight line drawn 50 
45      var clineStyle = `RGBA (% D,% D, D%, 0.5 )`
 46 is      for I: = 0 ; I < 50 ; I ++ {
 47          the lineStyle: = fmt.Sprintf (clineStyle, 155 + int (getRandomNum2 () * 10 ), 155 + int (getRandomNum () * 100 ), 155 + int(getRandomNum()*100))
 48         fmt.Println(lineStyle)
 49         context.Call("beginPath")
 50         context.Set("strokeStyle", lineStyle)
 51         context.Call("moveTo", getRandomNum()*width, getRandomNum()*height)
 52         context.Call("lineTo", getRandomNum()*width, getRandomNum()*height)
 53         context.Call("stroke")
 54     }
 55 
 56     context.Set("font", "30px Arial")
 57     context.Set("strokeStyle", "blue")
 58     for i := 0; i < 10; i++ {
 59         context.Call("strokeText", "hello wasm", (getRandomNum2()+1)*10+getRandomNum2()*10,(getRandomNum2 () + 10) *1+getRandomNum2()*50)
 60     }
 61 }
 62 
 63 func registerCallbackFunc() {
 64     cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
 65         fmt.Println("button clicked")
 66 
 67         num1 := getElementByID("num1").Get("value").String()
 68         v1, err := strconv.Atoi(num1)
 69         if nil != err {
 70             fmt.Println("button clicked:", num1, err.Error())
 71             jsAlert().Invoke(err.Error())
 72             // panic(err)
 73             return nil
 74         }
 75 
 76         num2 := getElementByID("num2").Get("value").String()
 77         v2, err := strconv.Atoi(num2)
 78         if nil != err {
 79             fmt.Println("button clicked:", num2, err.Error())
 80             // panic(err)
 81             return nil
 82         }
 83 
 84         rlt := v1 + v2
 85         getElementByID("rlt").Set("value", rlt)
 86 
 87         return nil
 88     })
 89 
 90     getElementByID("compute").Call("addEventListener", "click", cb)
 91 }
 92 
 93getElementByID FUNC (ID String ) js.Value {
 94      return js.Global (). the Get ( " Document " ) .CALL ( " the getElementById " , ID)
 95  }
 96  
97  FUNC jsAlert () js.Value {
 98      return js.Global () .Get ( " Alert " )
 99  }
 100  
101  FUNC main () {
 102      fmt.Println ( " the Hello, webassembly Go! " )
 103      Draw ()
 104      // by js.Global (). get () to get refers to the global alert function
105      alert:. = Js.Global () the Get ( " alert " )
 106      // call to call alert function alert.Invoke 
107      alert.Invoke ( " Hello World " )
 108  
109      registerCallbackFunc ()
 110 }
Go wasm Code

The code is compiled into Wasm file, you need to set the compiler environment. I use VsCode, can not always take effect with powershell set environment variables, then replaced Bash:

Execution: go env viewing environment, pay attention to GOOS and GOARCH, if the system is to win, then, should be the default windows and amd64, to compile wasm files need to be modified as follows:

export GOOS=js

export GOARCH=wasm

Otherwise, you will be prompted strange compile time information (instead of prompting environmental issues), or if not, you can set CGO:

export CGO_ENABLED=0

Of course, I set 1 is not the problem.

Finally compiled wasm file:

go build -o lib.wasm main.go

-o parameter is the compiler, specify the output file.

Go in there to introduce: syscall / js

). The Get () Gets js object via js.Global (, both functions can be acquired, may be acquired DOM elements. Type is js.Value.

Such as:

js.Global().Get("alert")
js.Global().Get("document")

If a property element is set to call Set (), if the call is (execution) method, call Call ( "function name", "Parameters").

Such as:

js.Global().Get("document").Call("getElementById", id)
 
Preceding code demonstrates a call alert (), read and write operations of Input, Canvas object.

Second, write HTML

 1 <html>
 2     <head>
 3         <meta charset="utf-8">
 4         <script src="wasm_exec.js"></script>
 5         <script>
 6             const go = new Go();
 7             WebAssembly.instantiateStreaming(fetch("lib.wasm"), go.importObject).then((result) => {
 8                 go.run(result.instance);
 9             });
10         </script>
11     </head>
12     <body>
13         <canvas id='canvas'></canvas></br>
14         <input id="num1" type="number" />
15         +
16         <input id="num2" type="number" />
17         =
18         <input id="rlt" type="number" readonly="readonly" />
19         <button id="compute">compute</button>
20     </body>
21 </html>
index.html

HTML file is the definition of interface elements introduced wasm_exec.js file, call just build the lib.wasm.

Third, write an HTTP service

Go built-in HTTP server supports Content-Type is application / wasm.

 1 package main
 2 
 3 import (
 4     "flag"
 5     "log"
 6     "net/http"
 7 )
 8 
 9 var (
10     listen = flag.String("listen", ":8087", "listen address")
11     dir    = flag.String("dir", ".", "files directory to serve")
12 )
13 
14 func main() {
15     flag.Parse()
16     log.Printf("listening on %q...", *listen)
17     err := http.ListenAndServe(*listen, http.FileServer(http.Dir(*dir)))
18     log.Fatalln(err)
19 }
HTTP service code

Here we must note: In order to compile wasm file before modifying the GOOS and GOARCH, now in order to run the http service, we must restore.

To facilitate debugging, we can create a new terminal in vscode inside, execute:

export GOOS=windows

export GOARCH=amd64

Then execute:

go run server.go

If there is a firewall prompt network access, select Allow, and then see the terminal prompt:

2020/03/10 09:27:12 listening on ":8087"...

This means that our HTTP service started well.

Fourth, the test results

Enter in the browser: http: //127.0.0.1: 8087 /

You can see the page pops up a dialog box:

 

 

Then came what we draw:

 

 

See the output content in a browser debugger inside:

 

 There is also a page of function calculation, we enter a number, click the button, found no response, see the debugger can see the error:

 

Prompt information is clear, look at our Go back to the code, main () function in the implementation of the registerCallbackFunc () on the end of the exit,

This time again certainly fail to call, so we can not let the program exits:

. 1  FUNC main () {
 2      fmt.Println ( " ! The Hello, webassembly Go " )
 . 3      Draw ()
 . 4      // reference to get a global alert function by js.Global () the Get (). 
. 5      alert: = js.Global () .Get ( " alert " )
 . 6      // call to call alert function alert.Invoke 
. 7      alert.Invoke ( " Hello World " )
 . 8      DONE: = the make (Chan struct {}, 0 ) // Create unbuffered channel 
9  
10      registerCallbackFunc ()
 . 11      <-done    // blocked 
12 }

Creating a channel on line 8, and then read content from 11 channels in line, because the channel has no content, it will be blocked.

Then recompile wasm file, refresh the page, you can see the expected reach:

 

 This is the basic routines developed by Go Wasm of the.

Guess you like

Origin www.cnblogs.com/codingnote/p/12453872.html