Eleanor McHugh


http://slideshare.net/feyeleanor


http://github.com/feyeleanor/TheBrowserEnvironment
The Browser Environment
A Systems Programmer's Perspective


[a rant in diverse movements]
TL;DR
JavaScript Concurrency is a Confused Mess


if you disagree you have serious Stockholm Syndrome
Elric of Melniboné, Michael Moorcock
E
lric sent his mind into twisting tunnels of logic,
across endless plains of ideas, through
mountains of symbolism and endless universes
of alternate truths; he sent his mind out further
and further and as it went he sent with it the words [...] words
that few of his contemporaries would understand...
pay attention!
all code is BSD 2-clause licensed


any resemblance to actual code &
conceptstm, living or dead, is probably
your imagination playing tricks on you


if you can make money from it you're
doing a damn sight better than we are!
In Digital Spaces
•2006 -> present [inidsol.uk]


•13 US patents


•real-time systems


•digital identity


•distributed ledgers


•DNS -> [TCP|UDP] -> HTTP


•Ruby -> Go -> JavaScript
Seeking Identity
Ellie

[physicist]
Romek

[cryptographer]
Since 2009
•http://leanpub.com/GoNotebook


•http://github.com/feyeleanor


•http://slideshare.net/feyeleanor
Abusing Go
HTTP[S]
serving web content with go
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


})


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}	


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>SERVING HTML</title>


</head>


<body>


<h1>SERVING HTML</h1>


<div>


hello world!


</div>


</body>


</html>
func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


})


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}	


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>SERVING HTML</title>


</head>


<body>


<h1>SERVING HTML</h1>


<div>


hello world!


</div>


</body>


</html>
func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


const CERT="cert.pem"


const KEY="key.pem"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}	


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>SERVING HTML</title>


</head>


<body>


<h1>SERVING HTML</h1>


<div>


hello world!


</div>


</body>


</html>
func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil))


}
Microsoft's Gift


to Humanity
the XMLHttpRequest object
aka


AJAX
asynchronous javascript and XML
AJAX
Asynchronous JavaScript and XML
•JavaScript is a single-threaded language


•but browsers are event-driven environments


•so JavaScript runtimes normally have three basic threads


•one to run the main script


•one to run scripts for high priority events


•one to run scripts for low priority events


•and each event can have callbacks de
fi
ned for it
AJAX
Asynchronous JavaScript and XML
•XMLHttpRequest
fi
rst appeared in MSXML


•available in IE5 as an ActiveX component from 1999


•similar functionality in other browsers from 2000 onwards


•fully supported in IE 7 2006


•despite its name it isn't restricted to XML


•most modern uses involve JSON
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>AJAX EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}


</script>


</head>


<body>


<h1>AJAX EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{


"A": AJAX_handler("A"),


"B": AJAX_handler("B"),


"C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>AJAX EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}


</script>


</head>


<body>


<h1>AJAX EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}


</button>


</span>


{{end}}
{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>AJAX EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.open("GET", "{{$c}}", false);


try {


xhttp.send();


print("event_log", xhttp.responseText);


} catch(err) {


print("event_log", `Request Failed: ${err}`);


}


}


{{end}}


</script>


</head>


<body>


<h1>AJAX EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.open("GET", "{{$c}}", false);


try {


xhttp.send();


print("event_log", xhttp.responseText);


} catch(err) {


print("event_log", `Request Failed: ${err}`);


}


}


{{end}}
fetch
a promise of things to come
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>FETCH EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


async function {{$c}}() {


let response = await fetch("{{$c}}");


if (response.ok) {


let body = await response.text();


print("event_log", body);


} else {


print("event_log", `Request Failed: ${response.status}`);


}


}


{{end}}


</script>


</head>


<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
{{range $c, $v := .Commands}}


async function {{$c}}() {


let response = await fetch("{{$c}}");


if (response.ok) {


let body = await response.text();


print("event_log", body);


} else {


print("event_log", `Request Failed: ${response.status}`);


}


}


{{end}}
{{range $c, $v := .Commands}}


async function {{$c}}() {


let response = await fetch("{{$c}}");


if (response.ok) {


let body = await response.text();


print("event_log", body);


} else {


print("event_log", `Request Failed: ${response.status}`);


}


}


{{end}}
{{range $c, $v := .Commands}}


async function {{$c}}() {


fetch("{{$c}}")


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


}


{{end}}
DOM
document object model
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>FETCH EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}


function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}


</script>


</head>


<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


<button id='A' type="button" onclick="toggle('A');">A</button>


<button id='B' type="button" onclick="toggle('B');">B</button>


<button id='C' type="button" onclick="toggle('C');">C</button>


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}


function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}
<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


<button id='A' type="button" onclick="toggle('A');">A</button>


<button id='B' type="button" onclick="toggle('B');">B</button>


<button id='C' type="button" onclick="toggle('C');">C</button>


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>
function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}


function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}
<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


<button id='A' type="button" onclick="toggle('A');">A</button>


<button id='B' type="button" onclick="toggle('B');">B</button>


<button id='C' type="button" onclick="toggle('C');">C</button>


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>DOM EXAMPLE</title>


<script>


function hide(e) {


e.innerHTML = "X";


}


function show(...e) {


e.forEach(e => {


e.innerHTML = e.id;


});


}


var buttons = [];


function toggle(e) {


hide(e);


switch(e.id) {


case 'A':


show(buttons[1], buttons[0]);


break;


case 'B':


show(buttons[2], buttons[0]);


break;


case 'C':


show(buttons[2], buttons[1]);


break;


};


}


function newButton(id) {


let b = document.createElement("BUTTON");


b.id = id;


b.onclick = new Function("toggle(this);");


b.appendChild(document.createTextNode(id));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


['A', 'B', 'C'].forEach(n => {


buttons.unshift(newButton(n));


button_bar.appendChild(buttons[0]);


});


};


</script>


</head>


<body>


<h1>DOM EXAMPLE</h1>


<h2>Known Actions</h2>


<div id="action_buttons"></div>


</body>


</html>
function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}
function hide(e) {


e.innerHTML = "X";


}


function show(...e) {


e.forEach(e => {


e.innerHTML = e.id;


});


}
function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}
var buttons = [];


function toggle(e) {


hide(e);


switch(e.id) {


case 'A':


show(buttons[1], buttons[0]);


break;


case 'B':


show(buttons[2], buttons[0]);


break;


case 'C':


show(buttons[2], buttons[1]);


break;


};


}
function newButton(id) {


let b = document.createElement("BUTTON");


b.id = id;


b.onclick = new Function("toggle(this);");


b.appendChild(document.createTextNode(id));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


['A', 'B', 'C'].forEach(n => {


buttons.unshift(newButton(n));


button_bar.appendChild(buttons[0]);


});


};
<body>


<h1>DOM EXAMPLE</h1>


<h2>Known Actions</h2>


<div id="action_buttons"></div>


</body>
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string]func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct{ Commands }


func main() {


p := PageCon
fi
guration{


Commands{


"A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


return func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>DOM FETCH EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


function doCommand(c) {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


};


</script>


</head>


<body>


<h1>DOM FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


};
function doCommand(c) {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


};
setInterval
marking time
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>TIMER EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}


</script>


</head>


<body>


<h1>TIMER EXAMPLE</h1>


<h2>Timer Events</h2>


<div id='event_log'></div>


</body>


</html>
window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}
window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>TIMER EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


const doAfter = (i, f) => { return window.setTimeout(f, i) };


const doEvery = (i, f) => { return window.setInterval(f, i) };


window.onload = () => {


let i = doEvery(500, () => {


print("event_log", "doEvery triggered");


);


doAfter(3000, () => {


print("event_log", "doAfter triggered");


doAfter(2000, () => {


window.clearInterval(i);


print("event_log", "doEvery cancelled");


});


});


}


</script>


</head>


<body>


<h1>TIMER EXAMPLE</h1>


<h2>Timer Events</h2>


<div id='event_log'></div>


</body>


</html>
const doAfter = (i, f) => { return window.setTimeout(f, i) };


const doEvery = (i, f) => { return window.setInterval(f, i) };


window.onload = () => {


let i = doEvery(500, () => {


print("event_log", "doEvery triggered");


});


doAfter(3000, () => {


print("event_log", "doAfter triggered");


doAfter(2000, () => {


window.clearInterval(i);


print("event_log", "doEvery cancelled");


});


});


}
window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}


window.onload = () => {


let i = doEvery(500, () => {


print("event_log", "doEvery triggered");


});


doAfter(3000, () => {


print("event_log", "doAfter triggered");


doAfter(2000, () => {


window.clearInterval(i);


print("event_log", "doEvery cancelled");


});


});


}
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string]func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct{ Commands }


func main() {


p := PageCon
fi
guration{


Commands{


"A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


return func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>TIMER FETCH EXAMPLE</title>


<script>


const print = (e, m) => document.getElementById(e).innerHTML += `<div>${m}</div>`;


const doEvery = (i, f) => { return window.setInterval(f, i) };


var timers = {}


function doCommand(c) {


if (timers[c]) {


print("event_log", `no longer polling ${c}`);


window.clearInterval(timers[c]);


timers[c] = null;


} else {


print("event_log", `polling ${c}`);


timers[c] = doEvery(500, () => {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


});


}


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


}


</script>


</head>


<body>


<h1>TIMER FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
var timers = {}


function doCommand(c) {


if (timers[c]) {


print("event_log", `no longer polling ${c}`);


window.clearInterval(timers[c]);


timers[c] = null;


} else {


print("event_log", `polling ${c}`);


timers[c] = doEvery(500, () => {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


});


}


}
var timers = {}


function doCommand(c) {


if (timers[c]) {


print("event_log", `no longer polling ${c}`);


window.clearInterval(timers[c]);


timers[c] = null;


} else {


print("event_log", `polling ${c}`);


timers[c] = doEvery(500, () => {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


});


}


}
WebSocket
bidirectional communication
package main


import "fmt"


import "log"


import "net/http"


import "os"


import "strings"


import "text/template"


import "golang.org/x/net/websocket"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


log.Printf("received: %vn", b.Message)


websocket.JSON.Send(ws, []interface{}{b.Message})


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>WebSocket EXAMPLE</title>


<script>


function print(m) {


document.getElementById("event_log").innerHTML += `<div>${m}</div>`;


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}


</script>


</head>


<body>


<h1>WebSocket EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
import "golang.org/x/net/websocket"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


log.Printf("received: %vn", b.Message)


websocket.JSON.Send(ws, []interface{}{b.Message})


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
import "golang.org/x/net/websocket"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


log.Printf("received: %vn", b.Message)


websocket.JSON.Send(ws, []interface{}{b.Message})


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}
window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}
package main


import "fmt"


import "log"


import "net/http"


import "os"


import "strings"


import "text/template"


import "golang.org/x/net/websocket"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


	 	 	 	 	
}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>WebSocket EXAMPLE</title>


<script>


function print(m) {


document.getElementById("event_log").innerHTML += `<div>${m}</div>`;


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}


</script>


</head>


<body>


<h1>WebSocket EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()
package main


import "log"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var m []interface{}


for {


if e := websocket.JSON.Receive(ws, &m); e == nil {


log.Printf("message: %vn", m)


} else {


log.Fatal(e)


}


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var m []interface{}


for {


if e := websocket.JSON.Receive(ws, &m); e == nil {


log.Printf("message: %vn", m)


} else {


log.Fatal(e)


}


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var m []interface{}


for {


if e := websocket.JSON.Receive(ws, &m); e == nil {


log.Printf("message: %vn", m)


} else {


log.Fatal(e)


}


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "os"


import "time"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var b struct{ Message string }


for _, v := range os.Args[1:] {


b.Message = v


websocket.JSON.Send(ws, &b)


time.Sleep(1 * time.Second)


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "os"


import "time"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var b struct{ Message string }


for _, v := range os.Args[1:] {


b.Message = v


websocket.JSON.Send(ws, &b)


time.Sleep(1 * time.Second)


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "os"


import "time"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var b struct{ Message string }


for _, v := range os.Args[1:] {


b.Message = v


websocket.JSON.Send(ws, &b)


time.Sleep(1 * time.Second)


}


} else {


log.Fatal(e)


}


}

The Browser Environment - A Systems Programmer's Perspective

  • 1.
    Eleanor McHugh http://slideshare.net/feyeleanor http://github.com/feyeleanor/TheBrowserEnvironment The BrowserEnvironment A Systems Programmer's Perspective [a rant in diverse movements]
  • 2.
    TL;DR JavaScript Concurrency isa Confused Mess if you disagree you have serious Stockholm Syndrome
  • 3.
    Elric of Melniboné,Michael Moorcock E lric sent his mind into twisting tunnels of logic, across endless plains of ideas, through mountains of symbolism and endless universes of alternate truths; he sent his mind out further and further and as it went he sent with it the words [...] words that few of his contemporaries would understand...
  • 4.
    pay attention! all codeis BSD 2-clause licensed any resemblance to actual code & conceptstm, living or dead, is probably your imagination playing tricks on you if you can make money from it you're doing a damn sight better than we are!
  • 5.
    In Digital Spaces •2006-> present [inidsol.uk] •13 US patents •real-time systems •digital identity •distributed ledgers •DNS -> [TCP|UDP] -> HTTP •Ruby -> Go -> JavaScript Seeking Identity Ellie [physicist] Romek [cryptographer]
  • 9.
  • 10.
  • 11.
    package main import "fmt" import"io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) }) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>SERVING HTML</title> </head> <body> <h1>SERVING HTML</h1> <div> hello world! </div> </body> </html>
  • 12.
    func main() { s:= strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) }) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) }
  • 13.
    package main import "fmt" import"io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>SERVING HTML</title> </head> <body> <h1>SERVING HTML</h1> <div> hello world! </div> </body> </html>
  • 14.
    func main() { s:= strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) }
  • 15.
    package main import "fmt" import"io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" const CERT="cert.pem" const KEY="key.pem" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>SERVING HTML</title> </head> <body> <h1>SERVING HTML</h1> <div> hello world! </div> </body> </html>
  • 16.
    func main() { s:= strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil)) }
  • 17.
    Microsoft's Gift to Humanity theXMLHttpRequest object
  • 18.
  • 19.
    AJAX Asynchronous JavaScript andXML •JavaScript is a single-threaded language •but browsers are event-driven environments •so JavaScript runtimes normally have three basic threads •one to run the main script •one to run scripts for high priority events •one to run scripts for low priority events •and each event can have callbacks de fi ned for it
  • 20.
    AJAX Asynchronous JavaScript andXML •XMLHttpRequest fi rst appeared in MSXML •available in IE5 as an ActiveX component from 1999 •similar functionality in other browsers from 2000 onwards •fully supported in IE 7 2006 •despite its name it isn't restricted to XML •most modern uses involve JSON
  • 21.
    package main import "fmt" import"net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>AJAX EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}} </script> </head> <body> <h1>AJAX EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 22.
    package main import "fmt" import"net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>AJAX EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}} </script> </head> <body> <h1>AJAX EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 23.
    {{range $c, $v:= .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}} {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}} </button> </span> {{end}}
  • 24.
    {{range $c, $v:= .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}}
  • 25.
    package main import "fmt" import"net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>AJAX EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.open("GET", "{{$c}}", false); try { xhttp.send(); print("event_log", xhttp.responseText); } catch(err) { print("event_log", `Request Failed: ${err}`); } } {{end}} </script> </head> <body> <h1>AJAX EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 26.
    {{range $c, $v:= .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.open("GET", "{{$c}}", false); try { xhttp.send(); print("event_log", xhttp.responseText); } catch(err) { print("event_log", `Request Failed: ${err}`); } } {{end}}
  • 27.
    fetch a promise ofthings to come
  • 28.
    package main import "fmt" import"net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>FETCH EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} async function {{$c}}() { let response = await fetch("{{$c}}"); if (response.ok) { let body = await response.text(); print("event_log", body); } else { print("event_log", `Request Failed: ${response.status}`); } } {{end}} </script> </head> <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 29.
    {{range $c, $v:= .Commands}} async function {{$c}}() { let response = await fetch("{{$c}}"); if (response.ok) { let body = await response.text(); print("event_log", body); } else { print("event_log", `Request Failed: ${response.status}`); } } {{end}}
  • 30.
    {{range $c, $v:= .Commands}} async function {{$c}}() { let response = await fetch("{{$c}}"); if (response.ok) { let body = await response.text(); print("event_log", body); } else { print("event_log", `Request Failed: ${response.status}`); } } {{end}}
  • 31.
    {{range $c, $v:= .Commands}} async function {{$c}}() { fetch("{{$c}}") .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); } {{end}}
  • 32.
  • 33.
    package main import "fmt" import"io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>FETCH EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } function hide(...n) { n.forEach(e => { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function toggle(name) { print("event_log", name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } </script> </head> <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> <button id='A' type="button" onclick="toggle('A');">A</button> <button id='B' type="button" onclick="toggle('B');">B</button> <button id='C' type="button" onclick="toggle('C');">C</button> </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 34.
    function hide(...n) { n.forEach(e=> { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function toggle(name) { print("event_log", name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> <button id='A' type="button" onclick="toggle('A');">A</button> <button id='B' type="button" onclick="toggle('B');">B</button> <button id='C' type="button" onclick="toggle('C');">C</button> </div> <h2>Server Output</h2> <div id='event_log'></div> </body>
  • 35.
    function hide(...n) { n.forEach(e=> { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function toggle(name) { print("event_log", name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> <button id='A' type="button" onclick="toggle('A');">A</button> <button id='B' type="button" onclick="toggle('B');">B</button> <button id='C' type="button" onclick="toggle('C');">C</button> </div> <h2>Server Output</h2> <div id='event_log'></div> </body>
  • 36.
    package main import "fmt" import"io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>DOM EXAMPLE</title> <script> function hide(e) { e.innerHTML = "X"; } function show(...e) { e.forEach(e => { e.innerHTML = e.id; }); } var buttons = []; function toggle(e) { hide(e); switch(e.id) { case 'A': show(buttons[1], buttons[0]); break; case 'B': show(buttons[2], buttons[0]); break; case 'C': show(buttons[2], buttons[1]); break; }; } function newButton(id) { let b = document.createElement("BUTTON"); b.id = id; b.onclick = new Function("toggle(this);"); b.appendChild(document.createTextNode(id)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); ['A', 'B', 'C'].forEach(n => { buttons.unshift(newButton(n)); button_bar.appendChild(buttons[0]); }); }; </script> </head> <body> <h1>DOM EXAMPLE</h1> <h2>Known Actions</h2> <div id="action_buttons"></div> </body> </html>
  • 37.
    function hide(...n) { n.forEach(e=> { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function hide(e) { e.innerHTML = "X"; } function show(...e) { e.forEach(e => { e.innerHTML = e.id; }); }
  • 38.
    function toggle(name) { print("event_log",name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } var buttons = []; function toggle(e) { hide(e); switch(e.id) { case 'A': show(buttons[1], buttons[0]); break; case 'B': show(buttons[2], buttons[0]); break; case 'C': show(buttons[2], buttons[1]); break; }; }
  • 39.
    function newButton(id) { letb = document.createElement("BUTTON"); b.id = id; b.onclick = new Function("toggle(this);"); b.appendChild(document.createTextNode(id)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); ['A', 'B', 'C'].forEach(n => { buttons.unshift(newButton(n)); button_bar.appendChild(buttons[0]); }); }; <body> <h1>DOM EXAMPLE</h1> <h2>Known Actions</h2> <div id="action_buttons"></div> </body>
  • 40.
    package main import "fmt" import"net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string]func(http.ResponseWriter, *http.Request) type PageCon fi guration struct{ Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>DOM FETCH EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } function doCommand(c) { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} }; </script> </head> <body> <h1>DOM FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 41.
    window.onload = ()=> { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} };
  • 42.
    function doCommand(c) { fetch(c) .then(response=> response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} };
  • 43.
  • 44.
    package main import "fmt" import"io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>TIMER EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } window.onload = () => { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); } </script> </head> <body> <h1>TIMER EXAMPLE</h1> <h2>Timer Events</h2> <div id='event_log'></div> </body> </html>
  • 45.
    window.onload = ()=> { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); }
  • 46.
    window.onload = ()=> { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); }
  • 47.
    package main import "fmt" import"io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>TIMER EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } const doAfter = (i, f) => { return window.setTimeout(f, i) }; const doEvery = (i, f) => { return window.setInterval(f, i) }; window.onload = () => { let i = doEvery(500, () => { print("event_log", "doEvery triggered"); ); doAfter(3000, () => { print("event_log", "doAfter triggered"); doAfter(2000, () => { window.clearInterval(i); print("event_log", "doEvery cancelled"); }); }); } </script> </head> <body> <h1>TIMER EXAMPLE</h1> <h2>Timer Events</h2> <div id='event_log'></div> </body> </html>
  • 48.
    const doAfter =(i, f) => { return window.setTimeout(f, i) }; const doEvery = (i, f) => { return window.setInterval(f, i) }; window.onload = () => { let i = doEvery(500, () => { print("event_log", "doEvery triggered"); }); doAfter(3000, () => { print("event_log", "doAfter triggered"); doAfter(2000, () => { window.clearInterval(i); print("event_log", "doEvery cancelled"); }); }); }
  • 49.
    window.onload = ()=> { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); } window.onload = () => { let i = doEvery(500, () => { print("event_log", "doEvery triggered"); }); doAfter(3000, () => { print("event_log", "doAfter triggered"); doAfter(2000, () => { window.clearInterval(i); print("event_log", "doEvery cancelled"); }); }); }
  • 50.
    package main import "fmt" import"net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string]func(http.ResponseWriter, *http.Request) type PageCon fi guration struct{ Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>TIMER FETCH EXAMPLE</title> <script> const print = (e, m) => document.getElementById(e).innerHTML += `<div>${m}</div>`; const doEvery = (i, f) => { return window.setInterval(f, i) }; var timers = {} function doCommand(c) { if (timers[c]) { print("event_log", `no longer polling ${c}`); window.clearInterval(timers[c]); timers[c] = null; } else { print("event_log", `polling ${c}`); timers[c] = doEvery(500, () => { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); }); } } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} } </script> </head> <body> <h1>TIMER FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 51.
    var timers ={} function doCommand(c) { if (timers[c]) { print("event_log", `no longer polling ${c}`); window.clearInterval(timers[c]); timers[c] = null; } else { print("event_log", `polling ${c}`); timers[c] = doEvery(500, () => { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); }); } }
  • 52.
    var timers ={} function doCommand(c) { if (timers[c]) { print("event_log", `no longer polling ${c}`); window.clearInterval(timers[c]); timers[c] = null; } else { print("event_log", `polling ${c}`); timers[c] = doEvery(500, () => { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); }); } }
  • 53.
  • 54.
    package main import "fmt" import"log" import "net/http" import "os" import "strings" import "text/template" import "golang.org/x/net/websocket" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type PageCon fi guration struct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { log.Printf("received: %vn", b.Message) websocket.JSON.Send(ws, []interface{}{b.Message}) } else { log.Printf("socket receive error: %vn", e) break } } })) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>WebSocket EXAMPLE</title> <script> function print(m) { document.getElementById("event_log").innerHTML += `<div>${m}</div>`; } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} } </script> </head> <body> <h1>WebSocket EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 55.
    import "golang.org/x/net/websocket" type PageCon fi gurationstruct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { log.Printf("received: %vn", b.Message) websocket.JSON.Send(ws, []interface{}{b.Message}) } else { log.Printf("socket receive error: %vn", e) break } } })) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) }
  • 56.
    import "golang.org/x/net/websocket" type PageCon fi gurationstruct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { log.Printf("received: %vn", b.Message) websocket.JSON.Send(ws, []interface{}{b.Message}) } else { log.Printf("socket receive error: %vn", e) break } } })) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) }
  • 57.
    window.onload = ()=> { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} }
  • 58.
    window.onload = ()=> { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} }
  • 59.
    package main import "fmt" import"log" import "net/http" import "os" import "strings" import "text/template" import "golang.org/x/net/websocket" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type PageCon fi guration struct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>WebSocket EXAMPLE</title> <script> function print(m) { document.getElementById("event_log").innerHTML += `<div>${m}</div>`; } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} } </script> </head> <body> <h1>WebSocket EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 60.
    func main() { p:= PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } }))
  • 61.
    func main() { p:= PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }()
  • 62.
    func main() { p:= PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } }))
  • 63.
    func main() { p:= PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }()
  • 64.
    package main import "log" import"golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var m []interface{} for { if e := websocket.JSON.Receive(ws, &m); e == nil { log.Printf("message: %vn", m) } else { log.Fatal(e) } } } else { log.Fatal(e) } }
  • 65.
    package main import "log" import"golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var m []interface{} for { if e := websocket.JSON.Receive(ws, &m); e == nil { log.Printf("message: %vn", m) } else { log.Fatal(e) } } } else { log.Fatal(e) } }
  • 66.
    package main import "log" import"golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var m []interface{} for { if e := websocket.JSON.Receive(ws, &m); e == nil { log.Printf("message: %vn", m) } else { log.Fatal(e) } } } else { log.Fatal(e) } }
  • 67.
    package main import "log" import"os" import "time" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var b struct{ Message string } for _, v := range os.Args[1:] { b.Message = v websocket.JSON.Send(ws, &b) time.Sleep(1 * time.Second) } } else { log.Fatal(e) } }
  • 68.
    package main import "log" import"os" import "time" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var b struct{ Message string } for _, v := range os.Args[1:] { b.Message = v websocket.JSON.Send(ws, &b) time.Sleep(1 * time.Second) } } else { log.Fatal(e) } }
  • 69.
    package main import "log" import"os" import "time" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var b struct{ Message string } for _, v := range os.Args[1:] { b.Message = v websocket.JSON.Send(ws, &b) time.Sleep(1 * time.Second) } } else { log.Fatal(e) } }