Go and GopherJS

18 February 2015

Dmitri Shuralyov

Software Engineer, Triggit

Overview

2

Go

3

Motivation

(From mmcgrana.github.io/2012/09/getting-started-with-go-on-heroku.html.)

4

Good for writing general code

Use packages to abstract out platform-specific implementation details:

Use general interfaces that can be implemented and provided:

type FileSystem interface {
    Opener
    Lstat(path string) (os.FileInfo, error)
    Stat(path string) (os.FileInfo, error)
    ReadDir(path string) ([]os.FileInfo, error)
    String() string
}
5

Go target platforms

6

GopherJS

7

GopherJS GitHub Repo

8

What is supported?

9

Demo.

Easy to get started.

$ go get -u github.com/gopherjs/gopherjs

$ gopherjs build
10

Reasons to use Go in frontend

11

Packages that can be compiled to JavaScript

go/parser and go/printer

func process(input string) string {
    // Parse the AST.
    fset := token.NewFileSet()
    fileAst, parseErr := parser.ParseFile(fset, "", input, parser.ParseComments|parser.AllErrors)

    // Print the AST.
    var config = &printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}
    var buf bytes.Buffer
    err := config.Fprint(&buf, fset, fileAst)
    if err != nil {
        panic(err)
    }

    // Append parsing errors, if any.
    if parseErr != nil {
        buf.WriteString("\n---\n" + parseErr.Error())
    }

    return buf.String()
}
12

Packages that can be compiled to JavaScript

github.com/russross/blackfriday
github.com/microcosm-cc/bluemonday
github.com/sourcegraph/syntaxhighlight
github.com/shurcooL/go/highlight_go
github.com/shurcooL/go/highlight_diff
go/format
github.com/shurcooL/markdownfmt/markdown

13

Packages that can be compiled to JavaScript

Achieving all that in the browser took minutes, because existing Go code could be reused:

import "github.com/shurcooL/go/github_flavored_markdown"

func run(event dom.Event) {
    output.SetInnerHTML(string(github_flavored_markdown.Markdown([]byte(input.Value))))
}

func main() {
    input.AddEventListener("input", false, run)
    input.Value = initial
    input.SelectionStart, input.SelectionEnd = len(initial), len(initial)
    run(nil)
}
14

Running Go code in the browser?

15

Running Go code in the browser?

16

APIs in the browser

17

APIs in the browser

18

GopherJS and JavaScript

godoc.org/github.com/gopherjs/gopherjs/js

Accessing native JavaScript APIs in Go code:

// document.write("Hello world!");

js.Global.Get("document").Call("write", "Hello world!")

Providing Go functionality to other JavaScript code:

someGoFunc := func() {
    ...
}
js.Global.Set("SomeFunction", someGoFunc)
19

Type conversions between Go types and JavaScript types

godoc.org/github.com/gopherjs/gopherjs/js

20

APIs in the browser

21

APIs in the browser

Source: github.com/gopherjs/gopherjs/wiki/bindings

22

APIs in the browser

23

Bindings to JS libraries

24

Go Wrappers

25

GopherJS Issue Resolution Times

"Wow, awesome 1 hour fix, that was fast! Thanks!"

"Wow, that was fast - thank you very much for your efforts! :)"

"Great work! Thank you!"

"Thanks for your prompt replies!"

14 hours to fix a compiler bug.

26

GopherJS GitHub Repo

27

github.com/shurcooL/play/95

Minor change of topic...

Demo.

View Source: gotools.org/github.com/shurcooL/play/95

(Also github.com/shurcooL/play/97 and github.com/shurcooL/Hover.)

28

Other Demos

29

Compile Errors

30

Compile Errors

output, err := markdown.Process("", 12345, nil)
if err != nil {
    panic(err)
}
31

Compile Errors

var _ io.Reader = markdownRenderer{}
32

Debugging

33

Debugging

34

Debugging

35

Debugging

36

Debugging

37

Debugging

38

Debugging

39

Performance

40

Performance

41

Performance

42

Performance

43

Size of generated code

44

Limitations

45

Limitations

46

Limitations

47

Limitations

48

Advantages

49

Takeaway

Which language you use in the frontend is a choice you have to make.

50

Something fun to try at home

51

Community

52

Thank you

Dmitri Shuralyov
Software Engineer, Triggit
shurcooL@gmail.com
https://github.com/shurcooL
@shurcooL

53

Extras

54

Packages that can be compiled to JavaScript

go/parser and go/printer

package main

import ("bytes"; "go/parser"; "go/printer"; "go/token"; "honnef.co/go/js/dom")

var document = dom.GetWindow().Document()

var input = document.GetElementByID("input").(*dom.HTMLTextAreaElement)
var output = document.GetElementByID("output").(dom.HTMLElement)

var initial = "package main\n\n..."

func run(_ dom.Event) {
    output.SetTextContent(process(input.Value))
}

func main() {
    input.AddEventListener("input", false, run)
    input.Value = initial
    input.SelectionStart, input.SelectionEnd = 153, 153
    run(nil)
}
55

Code Samples

shareIcon := document.GetElementByID("share-icon")
shareIcon.AddEventListener("click", false, func(event dom.Event) {
    event.PreventDefault()
    fmt.Println("clicked!")
})

Setting CSS style of an element.

shareIcon.Style().SetProperty("display", "none", "")
56

Thank you

Dmitri Shuralyov

Software Engineer, Triggit

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)