Go, JavaScript and You
Nebraska JavaScript Meetup
6 March 2018
John Hobbs
Infrastructure Engineer, Flywheel
John Hobbs
Infrastructure Engineer, Flywheel
GopherJS compiles Go code (golang.org) to pure JavaScript code. Its main purpose is to give you the opportunity to write front-end code in Go which will still run in all browsers.
// +build js package main func main() { println("Hello From Go") }
$ gopherjs serve serving at http://localhost:8080 and on port 8080 of any available addresses
localhost:8080/github.com/jmhobbs/nejs-golang-talk/examples/minimal/
<button id="click-me">Click Me</button> <div id="target"></div> <script src="dom.js"></script>
func main() { d := dom.GetWindow().Document() container := d.GetElementByID("target").(*dom.HTMLDivElement) button := d.GetElementByID("click-me").(*dom.HTMLButtonElement) button.AddEventListener("click", false, func(event dom.Event) { div := d.CreateElement("div").(*dom.HTMLDivElement) div.SetTextContent(fmt.Sprintf("I was created at %v", time.Now())) container.AppendChild(div) }) }
func main() { resp, err := http.Get("http://localhost:9090/tweets") if err != nil { println(err) return } if resp.StatusCode == 200 { b, err := ioutil.ReadAll(resp.Body) if err != nil { println(err) return } println(string(b)) } println(resp.Status) }
func main() { req := xhr.NewRequest("GET", "/tweets") req.ResponseType = "json" err := req.Send(nil) if err != nil { println(err) return } if req.Status == 200 { println(req.Response) } println(req.StatusText) }
6.8M net-http.js 132K xhr.js
// Fresh new item! var newItem = new TodoTxtItem(); newItem.text = "Cool!"; // Create an item from a string var existingItem = new TodoTxtItem( "(A) Try out jsTodoTxt" ); console.log( existingItem.priority ); // Logs "A"
type TodoTxtItem struct { *js.Object Text string `js:"text"` Priority string `js:"priority"` Complete bool `js:"complete"` Completed time.Time `js:"completed"` Date time.Time `js:"date"` Contexts []string `js:"contexts"` Projects []string `js:"projects"` }
func NewTodoTxtItem() *TodoTxtItem { return &TodoTxtItem{Object: js.Global.Get("TodoTxtItem").New()} } func (ti *TodoTxtItem) Parse(item string) { ti.Call("parse", item) } func (ti *TodoTxtItem) ToString() string { return ti.Call("toString").String() } func main() { ti := NewTodoTxtItem() ti.Parse("(A) Try out jsTodoTxt @Computer") println("Text:", ti.Text) println("Priority:", ti.Priority) println("Context:", ti.Contexts[0]) ti.Priority = "B" println(ti.ToString()) }
type Router struct { routes map[string]*js.Object } func (r Router) Set(route string, target *js.Object) { r.routes[route] = target } func (r Router) Get(route string) *js.Object { return r.routes[route] } func NewRouter() *js.Object { router := Router{make(map[string]*js.Object)} return js.MakeWrapper(router) }
func main() { js.Global.Set("Router", NewRouter) }
<script src="export.js"></script> <script> var router = new Router(); router.Set("/hello", function () { console.log("Hello World!"); }); router.Get("/hello")(); console.log(router.Get("/goodbye")); </script>
Unstable!
package main import ( "github.com/gopherjs/vecty" "github.com/gopherjs/vecty/elem" ) type HelloWorldComponent struct { vecty.Core } func main() { vecty.RenderBody(&HelloWorldComponent{}) } func (hw *HelloWorldComponent) Render() vecty.ComponentOrHTML { return elem.Body( vecty.Markup(vecty.Class("vecty-root-container")), vecty.Text("Hello World!"), ) }
func (hw *HelloWorldComponent) Render() vecty.ComponentOrHTML { return elem.Body( elem.Heading1(vecty.Text("Hello World!")), &ImageComponent{Image: "gopher.jpg", Caption: "Flight Ready Gopher"}, ) } type ImageComponent struct { vecty.Core Image string Caption string } func (im *ImageComponent) Render() vecty.ComponentOrHTML { return elem.Div( elem.Image(vecty.Markup(prop.Src(im.Image))), elem.Span(vecty.Text(im.Caption)), ) }
func main() { vecty.RenderBody(&HelloWorldComponent{HelloWhat: "World!"}) } func (hw *HelloWorldComponent) Render() vecty.ComponentOrHTML { return elem.Body( elem.Heading1(vecty.Text("Hello "+hw.HelloWhat)), elem.Input( vecty.Markup( prop.Value(hw.HelloWhat), event.Input(func(e *vecty.Event) { hw.HelloWhat = e.Target.Get("value").String() vecty.Rerender(hw) }), ), ), ) }
type PageView struct { vecty.Core Tweets []*TweetView } type TweetView struct { vecty.Core Text string Name string Screenname string Avatar string } func main() { pv := &PageView{} vecty.RenderBody(pv) pv.refresh() }
func (tv *TweetView) Render() vecty.ComponentOrHTML { return elem.ListItem( elem.Image(vecty.Markup(prop.Src(tv.Avatar))), elem.Div( vecty.Markup(vecty.Class("user")), elem.Span( vecty.Markup(vecty.Class("username")), vecty.Text(tv.Name), ), elem.Span( vecty.Markup(vecty.Class("screenname")), vecty.Text("@"+tv.Screenname), ), ), elem.Div( vecty.Markup(vecty.Class("tweet")), vecty.Text(tv.Text), ), ) }
github.com/neelance/go/tree/wasm-wip
Omaha Gophers
March 27th
Flywheel Underground
John Hobbs
Infrastructure Engineer, Flywheel