SlideShare a Scribd company logo
From Node to Go 
John Maxwell / @jmaxyz
The Agile League 
agileleague.com 
@agileleague
Functional Spec 
• Serve static HTML, CSS, and JS assets! 
• /xhr: HTTP endpoint! 
• {"now":"2014-08-12T03:29:23.721Z"}! 
• /ws: Websocket endpoint! 
• {"id":9,"now":"2014-08-12T03:30:03.398Z"}! 
• Sending “delay” param to /xhr or /ws will trigger a 
100ms delay in response
Demo time
"use strict"; 
var http = require('http'); 
var express = require('express'); 
var WebSocketServer = require('ws').Server; 
var app = express(); 
app.use(express.static("./public")); 
app.use(app.router); 
app.get('/xhr', function (req, res) { 
bufferResponse(function () { 
res.writeHead(200, {'Content-Type': 'application/json'}); 
res.end(buildResponse()); 
}, req.query.delay == '1'); 
}); 
var port = process.env.PORT || 3000; 
var server = http.createServer(app).listen(port); 
var wss = new WebSocketServer({server: server, path: "/ws"}); 
wss.on('connection', function(socket) { 
socket.on('message', function(message) { 
message = JSON.parse(message); 
bufferResponse(function () { 
socket.send(buildResponse({id: message.id})); 
}, message.delay == '1'); 
}); 
}); 
console.log("listening on " + port); 
var buildResponse = function (properties) { 
properties = properties || {}; 
properties.now = new Date(); 
return JSON.stringify(properties); 
}; 
var bufferResponse = function (responder, delay) { 
delay ? setTimeout(responder, 100) : responder(); 
}; 
Node Server
"use strict"; 
var http = require('http'); 
var express = require('express'); 
var WebSocketServer = require('ws').Server; 
var app = express(); 
app.use(express.static("./public")); 
app.use(app.router); 
app.get('/xhr', function (req, res) { 
bufferResponse(function () { 
res.writeHead(200, {'Content-Type': 'application/json'}); 
res.end(buildResponse()); 
}, req.query.delay == '1'); 
}); 
var port = process.env.PORT || 3000; 
var server = http.createServer(app).listen(port); 
var wss = new WebSocketServer({server: server, path: "/ws"}); 
wss.on('connection', function(socket) { 
socket.on('message', function(message) { 
message = JSON.parse(message); 
bufferResponse(function () { 
Node Server
"use strict"; 
var http = require('http'); 
var express = require('express'); 
var WebSocketServer = require('ws').Server; 
var app = express(); 
app.use(express.static("./public")); 
app.use(app.router); 
app.get('/xhr', function (req, res) { 
bufferResponse(function () { 
res.writeHead(200, {'Content-Type': 'application/json'}); 
res.end(buildResponse()); 
}, req.query.delay == '1'); 
}); 
var port = process.env.PORT || 3000; 
var server = http.createServer(app).listen(port); 
var wss = new WebSocketServer({server: server, path: "/ws"}); 
wss.on('connection', function(socket) { 
socket.on('message', function(message) { 
message = JSON.parse(message); 
bufferResponse(function () { 
Node Server
app.get('/xhr', function (req, res) { 
bufferResponse(function () { 
res.writeHead(200, {'Content-Type': 'application/Node Server 
json'}); 
res.end(buildResponse()); 
}, req.query.delay == '1'); 
}); 
var port = process.env.PORT || 3000; 
var server = http.createServer(app).listen(port); 
var wss = new WebSocketServer({server: server, path: "/ws"}); 
wss.on('connection', function(socket) { 
socket.on('message', function(message) { 
message = JSON.parse(message); 
bufferResponse(function () { 
socket.send(buildResponse({id: message.id})); 
}, message.delay == '1'); 
}); 
}); 
console.log("listening on " + port); 
var buildResponse = function (properties) { 
properties = properties || {}; 
properties.now = new Date(); 
return JSON.stringify(properties); 
};
message = JSON.parse(message); 
bufferResponse(function () { 
socket.send(buildResponse({id: message.id})); 
}, message.delay == '1'); 
}); 
}); 
console.log("listening on " + port); 
var buildResponse = function (properties) { 
properties = properties || {}; 
properties.now = new Date(); 
return JSON.stringify(properties); 
}; 
var bufferResponse = function (responder, delay) { 
delay ? setTimeout(responder, 100) : responder(); 
}; 
Node Server
Functional Spec 
• Serve static HTML, CSS, and JS assets! 
• /xhr: HTTP endpoint! 
• {"now":"2014-08-12T03:29:23.721Z"}! 
• /ws: Websocket endpoint! 
• {"id":9,"now":"2014-08-12T03:30:03.398Z"}! 
• Sending “delay” param to /xhr or /ws will trigger a 
100ms delay in response
Why Go?
Why Go?
Go Primer
Blocking I/O & 
Synchronous Execution
Capitalization is important 
• Identifiers (functions, methods, and types) are 
only exported if they are capitalized 
• No public/private keywords
Static Typing 
• Type of every identifier is set and cannot be altered! 
• Variables (function parameters and locals)! 
• Return values! 
• Elements of Structs, Maps, and Slices! 
• Channels! 
• Compile time enforcement! 
• Function arguments are passed by value
Concurrency Support 
• Goroutines! 
• Any function can be called under its own 
Goroutine! 
• Go organizes threads/processes internally! 
• Channels! 
• How Goroutines communicate
package main 
import ( 
"net/http" 
"github.com/gorilla/mux" 
"github.com/gorilla/websocket" 
"time" 
"encoding/json" 
"fmt" 
"os" 
) 
func main() { 
r := mux.NewRouter() 
r.HandleFunc("/xhr", handleXHR) 
r.HandleFunc("/ws", handleWS) 
r.PathPrefix("/").Handler( 
Web Server 
http.FileServer(http.Dir("./public/")), 
)
"os" 
) 
func main() { 
r := mux.NewRouter() 
r.HandleFunc("/xhr", handleXHR) 
r.HandleFunc("/ws", handleWS) 
r.PathPrefix("/").Handler( 
Web Server 
http.FileServer(http.Dir("./public/")), 
) 
port := os.Getenv("PORT") 
if port == "" { 
port = "8080" 
} 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r *http.Request) { 
if r.FormValue("delay") == "1" { 
time.Sleep(100 * time.Millisecond) 
} 
response, _ := json.Marshal(WebResponse{time.Now()}) 
w.Write(response)
"os" 
) 
func main() { 
r := mux.NewRouter() 
r.HandleFunc("/xhr", handleXHR) 
r.HandleFunc("/ws", handleWS) 
r.PathPrefix("/").Handler( 
main() 
http.FileServer(http.Dir("./public/")), 
) 
port := os.Getenv("PORT") 
if port == "" { 
port = "8080" 
} 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r 
*http.Request) {
if port == "" { 
port = "8080" 
} 
HTTP request handler 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r *http.Request) { 
if r.FormValue("delay") == "1" { 
time.Sleep(100 * time.Millisecond) 
} 
response, _ := json.Marshal(WebResponse{time.Now()}) 
w.Write(response) 
} 
type WebResponse struct { 
Now time.Time `json:"now"` 
} 
var upgrader = websocket.Upgrader{ 
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
}
if port == "" { 
port = "8080" 
} 
JSON serialization 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r *http.Request) { 
if r.FormValue("delay") == "1" { 
time.Sleep(100 * time.Millisecond) 
} 
response, _ := json.Marshal(WebResponse{time.Now()}) 
w.Write(response) 
} 
type WebResponse struct { 
Now time.Time `json:"now"` 
} 
var upgrader = websocket.Upgrader{ 
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
}
if port == "" { 
port = "8080" 
} 
JSON serialization 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r *http.Request) { 
if r.FormValue("delay") == "1" { 
time.Sleep(100 * time.Millisecond) 
} 
response, _ := json.Marshal(WebResponse{time.Now()}) 
w.Write(response) 
} 
type WebResponse struct { 
Now time.Time `json:"now"` 
} 
var upgrader = websocket.Upgrader{ 
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
}
"fmt" 
"os" 
) 
func main() { 
r := mux.NewRouter() 
r.HandleFunc("/xhr", handleXHR) 
r.HandleFunc("/ws", handleWS) 
r.PathPrefix("/").Handler( 
http.FileServer(http.Dir("./public/")), 
) 
port := os.Getenv("PORT") 
if port == "" { 
port = "8080" 
} 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r *http.Request) { 
if r.FormValue("delay") == "1" { 
time.Sleep(100 * time.Millisecond) 
} 
response, _ := json.Marshal(WebResponse{time.Now()}) 
w.Write(response) 
} 
type WebResponse struct { 
Now time.Time `json:"now"` 
} 
var upgrader = websocket.Upgrader{ 
ReadBufferSize: 1024, 
Web Server
w.Write(response) 
} 
type WebResponse struct { 
Now time.Time `json:"now"` 
} 
var upgrader = websocket.Upgrader{ 
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) { 
for { 
content, more := <-writes 
conn.WriteJSON(content) 
if !more { 
return 
} 
} 
} 
type WSRequest struct { 
Id int `json:id` 
Delay bool `json:delay` 
} 
func (request *WSRequest) respond( 
writes chan WSResponse) { 
if request.Delay { 
time.Sleep(100 * time.Millisecond) 
} 
response := WSResponse{time.Now(), request.Id} 
writes <- response 
} 
type WSResponse struct { 
Now time.Time `json:"now"` 
Id int `json:"id"` 
} 
WebSocket Server
"os" 
) 
func main() { 
r := mux.NewRouter() 
r.HandleFunc("/xhr", handleXHR) 
r.HandleFunc("/ws", handleWS) 
r.PathPrefix("/").Handler( 
Integration with Web Server 
http.FileServer(http.Dir("./public/")), 
) 
port := os.Getenv("PORT") 
if port == "" { 
port = "8080" 
} 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r 
*http.Request) { 
if r.FormValue("delay") == "1" {
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
WebSocket Server 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) {
Now time.Time `json:"now"` 
} 
var upgrader = websocket.Upgrader{ 
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
close(writes) 
return 
} 
go message.respond(writes) 
} 
Open Connection
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
WebSocket Server 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) {
Order of operations 
1. Listen for new messages 
2. Send the responses 
3. Then close the connection
Order of implementation 
1. Send the responses 
2. Listen for new messages 
3. Then close the connection
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
WebSocket Server 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) {
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
Enable concurrent responses 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) {
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) { 
Receive and Send Responses 
for { 
content, more := <-writes 
conn.WriteJSON(content) 
if !more { 
return 
} 
} 
} 
type WSRequest struct { 
Id int `json:id` 
Delay bool `json:delay`
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
Enable concurrent responses 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) {
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
Listen on Connection 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) {
} 
} 
type WSRequest struct { 
Id int `json:id` 
Delay bool `json:delay` 
} 
func (request *WSRequest) respond( 
writes chan WSResponse) { 
if request.Delay { 
time.Sleep(100 * time.Millisecond) 
} 
response := WSResponse{time.Now(), request.Id} 
writes <- response 
} 
type WSResponse struct { 
Now time.Time `json:"now"` 
Id int `json:"id"` 
} 
Build Response
package main 
import ( 
"net/http" 
"github.com/gorilla/mux" 
"github.com/gorilla/websocket" 
"time" 
"encoding/json" 
"fmt" 
"os" 
) 
func main() { 
r := mux.NewRouter() 
r.HandleFunc("/xhr", handleXHR) 
r.HandleFunc("/ws", handleWS) 
r.PathPrefix("/").Handler( 
http.FileServer(http.Dir("./public/")), 
) 
port := os.Getenv("PORT") 
if port == "" { 
port = "8080" 
} 
fmt.Printf("listening on %sn", port) 
http.ListenAndServe(":" + port, r) 
} 
func handleXHR(w http.ResponseWriter, r *http.Request) { 
if r.FormValue("delay") == "1" { 
time.Sleep(100 * time.Millisecond) 
} 
response, _ := json.Marshal(WebResponse{time.Now()}) 
w.Write(response) 
} 
type WebResponse struct { 
Now time.Time `json:"now"` 
} 
var upgrader = websocket.Upgrader{ 
ReadBufferSize: 1024, 
WriteBufferSize: 1024, 
} 
func handleWS(w http.ResponseWriter, r *http.Request) { 
conn, err := upgrader.Upgrade(w, r, nil) 
if err != nil { 
return 
} 
writes := make(chan WSResponse) 
go respondWS(conn, writes) 
for { 
message := WSRequest{} 
err := conn.ReadJSON(&message) 
if err != nil { 
close(writes) 
return 
} 
go message.respond(writes) 
} 
} 
func respondWS(conn *websocket.Conn, 
writes chan WSResponse) { 
for { 
content, more := <-writes 
conn.WriteJSON(content) 
if !more { 
return 
} 
} 
} 
type WSRequest struct { 
Id int `json:id` 
Delay bool `json:delay` 
} 
func (request *WSRequest) respond( 
writes chan WSResponse) { 
if request.Delay { 
time.Sleep(100 * time.Millisecond) 
} 
response := WSResponse{time.Now(), request.Id} 
writes <- response 
} 
type WSResponse struct { 
Now time.Time `json:"now"` 
Id int `json:"id"` 
} 
Go Server
What’s the score? 
• 88 lines of Go vs 39 lines of JavaScript! 
• JSON interaction was kind of clunky! 
• Haven’t figured out how to deploy to Heroku! 
• Doing what the cool kids are doing
“ A straightforward translation of a C++ 
or Java program into Go is unlikely to 
produce a satisfactory result—Java 
programs are written in Java, not Go.” 
–Effective Go
“ A straightforward translation of a C++ 
or Java JavaScript program into Go is 
unlikely to produce a satisfactory result 
—Java JavaScript programs are written 
in Java JavaScript, not Go.”
John Maxwell 
john@agileleague.com 
@jmaxyz 
agileleague.com 
@agileleague

More Related Content

What's hot

Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
Bram Vogelaar
 
Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2
Cong Zhang
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
Bram Vogelaar
 
Lua tech talk
Lua tech talkLua tech talk
Lua tech talk
Locaweb
 
Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStack
Bram Vogelaar
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
Bram Vogelaar
 
Paris Kafka Meetup - How to develop with Kafka
Paris Kafka Meetup - How to develop with KafkaParis Kafka Meetup - How to develop with Kafka
Paris Kafka Meetup - How to develop with Kafka
Florian Hussonnois
 
Nginx-lua
Nginx-luaNginx-lua
Using ngx_lua in upyun 2
Using ngx_lua in upyun 2Using ngx_lua in upyun 2
Using ngx_lua in upyun 2
OpenRestyCon
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Brian Sam-Bodden
 
Building Your First Data Science Applicatino in MongoDB
Building Your First Data Science Applicatino in MongoDBBuilding Your First Data Science Applicatino in MongoDB
Building Your First Data Science Applicatino in MongoDB
MongoDB
 
TDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com GoTDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com Go
tdc-globalcode
 
RestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message QueueRestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message Queue
Gleicon Moraes
 
OneRing @ OSCamp 2010
OneRing @ OSCamp 2010OneRing @ OSCamp 2010
OneRing @ OSCamp 2010
Qiangning Hong
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScriptQiangning Hong
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii
명철 강
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
Felix Geisendörfer
 
Beyond Phoenix
Beyond PhoenixBeyond Phoenix
Beyond Phoenix
Gabriele Lana
 
神に近づくx/net/context (Finding God with x/net/context)
神に近づくx/net/context (Finding God with x/net/context)神に近づくx/net/context (Finding God with x/net/context)
神に近づくx/net/context (Finding God with x/net/context)
guregu
 
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
John Kim
 

What's hot (20)

Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
 
Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
 
Lua tech talk
Lua tech talkLua tech talk
Lua tech talk
 
Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStack
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
 
Paris Kafka Meetup - How to develop with Kafka
Paris Kafka Meetup - How to develop with KafkaParis Kafka Meetup - How to develop with Kafka
Paris Kafka Meetup - How to develop with Kafka
 
Nginx-lua
Nginx-luaNginx-lua
Nginx-lua
 
Using ngx_lua in upyun 2
Using ngx_lua in upyun 2Using ngx_lua in upyun 2
Using ngx_lua in upyun 2
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
 
Building Your First Data Science Applicatino in MongoDB
Building Your First Data Science Applicatino in MongoDBBuilding Your First Data Science Applicatino in MongoDB
Building Your First Data Science Applicatino in MongoDB
 
TDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com GoTDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com Go
 
RestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message QueueRestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message Queue
 
OneRing @ OSCamp 2010
OneRing @ OSCamp 2010OneRing @ OSCamp 2010
OneRing @ OSCamp 2010
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
 
Beyond Phoenix
Beyond PhoenixBeyond Phoenix
Beyond Phoenix
 
神に近づくx/net/context (Finding God with x/net/context)
神に近づくx/net/context (Finding God with x/net/context)神に近づくx/net/context (Finding God with x/net/context)
神に近づくx/net/context (Finding God with x/net/context)
 
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
DEVIEW - 오픈소스를 활용한 분산아키텍처 구현기술
 

Viewers also liked

Arnetwiki – requirement and design
Arnetwiki – requirement and designArnetwiki – requirement and design
Arnetwiki – requirement and designThree Lee
 
functional spec
functional specfunctional spec
functional specc.west
 
Tutorial of design basics
Tutorial of design basicsTutorial of design basics
Tutorial of design basicsThree Lee
 
8 Secrets Of Success
8 Secrets Of Success8 Secrets Of Success
8 Secrets Of Success
Sehar Khan
 
5 Tips for Maximizing Success Potential
5 Tips for Maximizing Success Potential5 Tips for Maximizing Success Potential
5 Tips for Maximizing Success Potential
NeuIMC
 
Maximizing Your Potential
Maximizing Your PotentialMaximizing Your Potential
Maximizing Your Potential
Neville Hobson
 
The Power Within
The Power WithinThe Power Within
The Power Within
Neville Hobson
 
The 8 traits successful people have in common
The 8 traits successful people have in commonThe 8 traits successful people have in common
The 8 traits successful people have in common
komali sunkara
 
Richard St. John - 8 To Be Great
Richard St. John -  8 To Be GreatRichard St. John -  8 To Be Great
Richard St. John - 8 To Be Great
tobibeer
 
8 secrets-of-success-ppt-video-and-discussion
8 secrets-of-success-ppt-video-and-discussion8 secrets-of-success-ppt-video-and-discussion
8 secrets-of-success-ppt-video-and-discussion
Isabel Breda
 
The 7 Secrets of Success
The 7 Secrets of SuccessThe 7 Secrets of Success
The 7 Secrets of Success
Hussein Hallak
 
Human values
Human valuesHuman values
Human values
Frank Calberg
 
Human values
Human valuesHuman values
Human values
Hitesh Sharma
 
How To Succeed.Ppt
How To Succeed.PptHow To Succeed.Ppt
How To Succeed.Ppt
Ramya.S. Gowda
 
How to be successful in life
How to be successful in lifeHow to be successful in life
How to be successful in life
ATEES Industrial Training Pvt Ltd
 
Learning in a Multi-device World
Learning in a Multi-device WorldLearning in a Multi-device World
Learning in a Multi-device World
Upside Learning Solutions
 
Intro To Hadoop
Intro To HadoopIntro To Hadoop
Intro To Hadoop
Bill Graham
 
Native, Hybrid, Web Apps?
Native, Hybrid, Web Apps? Native, Hybrid, Web Apps?
Native, Hybrid, Web Apps?
Upside Learning Solutions
 
17 Ways Successful People Approach Life
17 Ways Successful People Approach Life17 Ways Successful People Approach Life
17 Ways Successful People Approach Life
Brian Downard
 
Best Marketing Advice - 100 Global Experts Share Their Career Wisdom
Best Marketing Advice - 100 Global Experts Share Their Career WisdomBest Marketing Advice - 100 Global Experts Share Their Career Wisdom
Best Marketing Advice - 100 Global Experts Share Their Career Wisdom
Heidi Cohen
 

Viewers also liked (20)

Arnetwiki – requirement and design
Arnetwiki – requirement and designArnetwiki – requirement and design
Arnetwiki – requirement and design
 
functional spec
functional specfunctional spec
functional spec
 
Tutorial of design basics
Tutorial of design basicsTutorial of design basics
Tutorial of design basics
 
8 Secrets Of Success
8 Secrets Of Success8 Secrets Of Success
8 Secrets Of Success
 
5 Tips for Maximizing Success Potential
5 Tips for Maximizing Success Potential5 Tips for Maximizing Success Potential
5 Tips for Maximizing Success Potential
 
Maximizing Your Potential
Maximizing Your PotentialMaximizing Your Potential
Maximizing Your Potential
 
The Power Within
The Power WithinThe Power Within
The Power Within
 
The 8 traits successful people have in common
The 8 traits successful people have in commonThe 8 traits successful people have in common
The 8 traits successful people have in common
 
Richard St. John - 8 To Be Great
Richard St. John -  8 To Be GreatRichard St. John -  8 To Be Great
Richard St. John - 8 To Be Great
 
8 secrets-of-success-ppt-video-and-discussion
8 secrets-of-success-ppt-video-and-discussion8 secrets-of-success-ppt-video-and-discussion
8 secrets-of-success-ppt-video-and-discussion
 
The 7 Secrets of Success
The 7 Secrets of SuccessThe 7 Secrets of Success
The 7 Secrets of Success
 
Human values
Human valuesHuman values
Human values
 
Human values
Human valuesHuman values
Human values
 
How To Succeed.Ppt
How To Succeed.PptHow To Succeed.Ppt
How To Succeed.Ppt
 
How to be successful in life
How to be successful in lifeHow to be successful in life
How to be successful in life
 
Learning in a Multi-device World
Learning in a Multi-device WorldLearning in a Multi-device World
Learning in a Multi-device World
 
Intro To Hadoop
Intro To HadoopIntro To Hadoop
Intro To Hadoop
 
Native, Hybrid, Web Apps?
Native, Hybrid, Web Apps? Native, Hybrid, Web Apps?
Native, Hybrid, Web Apps?
 
17 Ways Successful People Approach Life
17 Ways Successful People Approach Life17 Ways Successful People Approach Life
17 Ways Successful People Approach Life
 
Best Marketing Advice - 100 Global Experts Share Their Career Wisdom
Best Marketing Advice - 100 Global Experts Share Their Career WisdomBest Marketing Advice - 100 Global Experts Share Their Career Wisdom
Best Marketing Advice - 100 Global Experts Share Their Career Wisdom
 

Similar to From Node to Go

Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Ismael Celis
 
JUDCon Brazil 2013 - Vert.x an introduction
JUDCon Brazil 2013 - Vert.x an introductionJUDCon Brazil 2013 - Vert.x an introduction
JUDCon Brazil 2013 - Vert.x an introductionSamuel Tauil
 
Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to Nodejs
Gabriele Lana
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
Peter Friese
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
Oleg Podsechin
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
Mike Brevoort
 
Intro to Node
Intro to NodeIntro to Node
Intro to Node
Aaron Stannard
 
Get Real: Adventures in realtime web apps
Get Real: Adventures in realtime web appsGet Real: Adventures in realtime web apps
Get Real: Adventures in realtime web apps
daviddemello
 
Android and REST
Android and RESTAndroid and REST
Android and REST
Roman Woźniak
 
Sharding and Load Balancing in Scala - Twitter's Finagle
Sharding and Load Balancing in Scala - Twitter's FinagleSharding and Load Balancing in Scala - Twitter's Finagle
Sharding and Load Balancing in Scala - Twitter's Finagle
Geoff Ballinger
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Tom Croucher
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
Sam Brannen
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
Gabriele Lana
 
Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02
Sunny Gupta
 
node.js workshop- node.js middleware
node.js workshop- node.js middlewarenode.js workshop- node.js middleware
node.js workshop- node.js middlewareQiong Wu
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...Tom Croucher
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interface
Joakim Gustin
 

Similar to From Node to Go (20)

Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
JUDCon Brazil 2013 - Vert.x an introduction
JUDCon Brazil 2013 - Vert.x an introductionJUDCon Brazil 2013 - Vert.x an introduction
JUDCon Brazil 2013 - Vert.x an introduction
 
Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to Nodejs
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
 
Intro to Node
Intro to NodeIntro to Node
Intro to Node
 
Get Real: Adventures in realtime web apps
Get Real: Adventures in realtime web appsGet Real: Adventures in realtime web apps
Get Real: Adventures in realtime web apps
 
Android and REST
Android and RESTAndroid and REST
Android and REST
 
Sharding and Load Balancing in Scala - Twitter's Finagle
Sharding and Load Balancing in Scala - Twitter's FinagleSharding and Load Balancing in Scala - Twitter's Finagle
Sharding and Load Balancing in Scala - Twitter's Finagle
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02
 
node.js workshop- node.js middleware
node.js workshop- node.js middlewarenode.js workshop- node.js middleware
node.js workshop- node.js middleware
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interface
 

Recently uploaded

Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
Elena Simperl
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 

Recently uploaded (20)

Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 

From Node to Go

  • 1. From Node to Go John Maxwell / @jmaxyz
  • 2. The Agile League agileleague.com @agileleague
  • 3.
  • 4.
  • 5. Functional Spec • Serve static HTML, CSS, and JS assets! • /xhr: HTTP endpoint! • {"now":"2014-08-12T03:29:23.721Z"}! • /ws: Websocket endpoint! • {"id":9,"now":"2014-08-12T03:30:03.398Z"}! • Sending “delay” param to /xhr or /ws will trigger a 100ms delay in response
  • 7.
  • 8. "use strict"; var http = require('http'); var express = require('express'); var WebSocketServer = require('ws').Server; var app = express(); app.use(express.static("./public")); app.use(app.router); app.get('/xhr', function (req, res) { bufferResponse(function () { res.writeHead(200, {'Content-Type': 'application/json'}); res.end(buildResponse()); }, req.query.delay == '1'); }); var port = process.env.PORT || 3000; var server = http.createServer(app).listen(port); var wss = new WebSocketServer({server: server, path: "/ws"}); wss.on('connection', function(socket) { socket.on('message', function(message) { message = JSON.parse(message); bufferResponse(function () { socket.send(buildResponse({id: message.id})); }, message.delay == '1'); }); }); console.log("listening on " + port); var buildResponse = function (properties) { properties = properties || {}; properties.now = new Date(); return JSON.stringify(properties); }; var bufferResponse = function (responder, delay) { delay ? setTimeout(responder, 100) : responder(); }; Node Server
  • 9. "use strict"; var http = require('http'); var express = require('express'); var WebSocketServer = require('ws').Server; var app = express(); app.use(express.static("./public")); app.use(app.router); app.get('/xhr', function (req, res) { bufferResponse(function () { res.writeHead(200, {'Content-Type': 'application/json'}); res.end(buildResponse()); }, req.query.delay == '1'); }); var port = process.env.PORT || 3000; var server = http.createServer(app).listen(port); var wss = new WebSocketServer({server: server, path: "/ws"}); wss.on('connection', function(socket) { socket.on('message', function(message) { message = JSON.parse(message); bufferResponse(function () { Node Server
  • 10. "use strict"; var http = require('http'); var express = require('express'); var WebSocketServer = require('ws').Server; var app = express(); app.use(express.static("./public")); app.use(app.router); app.get('/xhr', function (req, res) { bufferResponse(function () { res.writeHead(200, {'Content-Type': 'application/json'}); res.end(buildResponse()); }, req.query.delay == '1'); }); var port = process.env.PORT || 3000; var server = http.createServer(app).listen(port); var wss = new WebSocketServer({server: server, path: "/ws"}); wss.on('connection', function(socket) { socket.on('message', function(message) { message = JSON.parse(message); bufferResponse(function () { Node Server
  • 11. app.get('/xhr', function (req, res) { bufferResponse(function () { res.writeHead(200, {'Content-Type': 'application/Node Server json'}); res.end(buildResponse()); }, req.query.delay == '1'); }); var port = process.env.PORT || 3000; var server = http.createServer(app).listen(port); var wss = new WebSocketServer({server: server, path: "/ws"}); wss.on('connection', function(socket) { socket.on('message', function(message) { message = JSON.parse(message); bufferResponse(function () { socket.send(buildResponse({id: message.id})); }, message.delay == '1'); }); }); console.log("listening on " + port); var buildResponse = function (properties) { properties = properties || {}; properties.now = new Date(); return JSON.stringify(properties); };
  • 12. message = JSON.parse(message); bufferResponse(function () { socket.send(buildResponse({id: message.id})); }, message.delay == '1'); }); }); console.log("listening on " + port); var buildResponse = function (properties) { properties = properties || {}; properties.now = new Date(); return JSON.stringify(properties); }; var bufferResponse = function (responder, delay) { delay ? setTimeout(responder, 100) : responder(); }; Node Server
  • 13. Functional Spec • Serve static HTML, CSS, and JS assets! • /xhr: HTTP endpoint! • {"now":"2014-08-12T03:29:23.721Z"}! • /ws: Websocket endpoint! • {"id":9,"now":"2014-08-12T03:30:03.398Z"}! • Sending “delay” param to /xhr or /ws will trigger a 100ms delay in response
  • 15.
  • 16.
  • 19. Blocking I/O & Synchronous Execution
  • 20. Capitalization is important • Identifiers (functions, methods, and types) are only exported if they are capitalized • No public/private keywords
  • 21. Static Typing • Type of every identifier is set and cannot be altered! • Variables (function parameters and locals)! • Return values! • Elements of Structs, Maps, and Slices! • Channels! • Compile time enforcement! • Function arguments are passed by value
  • 22. Concurrency Support • Goroutines! • Any function can be called under its own Goroutine! • Go organizes threads/processes internally! • Channels! • How Goroutines communicate
  • 23. package main import ( "net/http" "github.com/gorilla/mux" "github.com/gorilla/websocket" "time" "encoding/json" "fmt" "os" ) func main() { r := mux.NewRouter() r.HandleFunc("/xhr", handleXHR) r.HandleFunc("/ws", handleWS) r.PathPrefix("/").Handler( Web Server http.FileServer(http.Dir("./public/")), )
  • 24. "os" ) func main() { r := mux.NewRouter() r.HandleFunc("/xhr", handleXHR) r.HandleFunc("/ws", handleWS) r.PathPrefix("/").Handler( Web Server http.FileServer(http.Dir("./public/")), ) port := os.Getenv("PORT") if port == "" { port = "8080" } fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) { if r.FormValue("delay") == "1" { time.Sleep(100 * time.Millisecond) } response, _ := json.Marshal(WebResponse{time.Now()}) w.Write(response)
  • 25. "os" ) func main() { r := mux.NewRouter() r.HandleFunc("/xhr", handleXHR) r.HandleFunc("/ws", handleWS) r.PathPrefix("/").Handler( main() http.FileServer(http.Dir("./public/")), ) port := os.Getenv("PORT") if port == "" { port = "8080" } fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) {
  • 26. if port == "" { port = "8080" } HTTP request handler fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) { if r.FormValue("delay") == "1" { time.Sleep(100 * time.Millisecond) } response, _ := json.Marshal(WebResponse{time.Now()}) w.Write(response) } type WebResponse struct { Now time.Time `json:"now"` } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, }
  • 27. if port == "" { port = "8080" } JSON serialization fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) { if r.FormValue("delay") == "1" { time.Sleep(100 * time.Millisecond) } response, _ := json.Marshal(WebResponse{time.Now()}) w.Write(response) } type WebResponse struct { Now time.Time `json:"now"` } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, }
  • 28. if port == "" { port = "8080" } JSON serialization fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) { if r.FormValue("delay") == "1" { time.Sleep(100 * time.Millisecond) } response, _ := json.Marshal(WebResponse{time.Now()}) w.Write(response) } type WebResponse struct { Now time.Time `json:"now"` } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, }
  • 29. "fmt" "os" ) func main() { r := mux.NewRouter() r.HandleFunc("/xhr", handleXHR) r.HandleFunc("/ws", handleWS) r.PathPrefix("/").Handler( http.FileServer(http.Dir("./public/")), ) port := os.Getenv("PORT") if port == "" { port = "8080" } fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) { if r.FormValue("delay") == "1" { time.Sleep(100 * time.Millisecond) } response, _ := json.Marshal(WebResponse{time.Now()}) w.Write(response) } type WebResponse struct { Now time.Time `json:"now"` } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, Web Server
  • 30. w.Write(response) } type WebResponse struct { Now time.Time `json:"now"` } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) { for { content, more := <-writes conn.WriteJSON(content) if !more { return } } } type WSRequest struct { Id int `json:id` Delay bool `json:delay` } func (request *WSRequest) respond( writes chan WSResponse) { if request.Delay { time.Sleep(100 * time.Millisecond) } response := WSResponse{time.Now(), request.Id} writes <- response } type WSResponse struct { Now time.Time `json:"now"` Id int `json:"id"` } WebSocket Server
  • 31. "os" ) func main() { r := mux.NewRouter() r.HandleFunc("/xhr", handleXHR) r.HandleFunc("/ws", handleWS) r.PathPrefix("/").Handler( Integration with Web Server http.FileServer(http.Dir("./public/")), ) port := os.Getenv("PORT") if port == "" { port = "8080" } fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) { if r.FormValue("delay") == "1" {
  • 32. ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { WebSocket Server close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) {
  • 33. Now time.Time `json:"now"` } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { close(writes) return } go message.respond(writes) } Open Connection
  • 34. ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { WebSocket Server close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) {
  • 35. Order of operations 1. Listen for new messages 2. Send the responses 3. Then close the connection
  • 36. Order of implementation 1. Send the responses 2. Listen for new messages 3. Then close the connection
  • 37. ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { WebSocket Server close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) {
  • 38. ReadBufferSize: 1024, WriteBufferSize: 1024, } Enable concurrent responses func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) {
  • 39. } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) { Receive and Send Responses for { content, more := <-writes conn.WriteJSON(content) if !more { return } } } type WSRequest struct { Id int `json:id` Delay bool `json:delay`
  • 40. ReadBufferSize: 1024, WriteBufferSize: 1024, } Enable concurrent responses func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) {
  • 41. ReadBufferSize: 1024, WriteBufferSize: 1024, } Listen on Connection func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) {
  • 42. } } type WSRequest struct { Id int `json:id` Delay bool `json:delay` } func (request *WSRequest) respond( writes chan WSResponse) { if request.Delay { time.Sleep(100 * time.Millisecond) } response := WSResponse{time.Now(), request.Id} writes <- response } type WSResponse struct { Now time.Time `json:"now"` Id int `json:"id"` } Build Response
  • 43. package main import ( "net/http" "github.com/gorilla/mux" "github.com/gorilla/websocket" "time" "encoding/json" "fmt" "os" ) func main() { r := mux.NewRouter() r.HandleFunc("/xhr", handleXHR) r.HandleFunc("/ws", handleWS) r.PathPrefix("/").Handler( http.FileServer(http.Dir("./public/")), ) port := os.Getenv("PORT") if port == "" { port = "8080" } fmt.Printf("listening on %sn", port) http.ListenAndServe(":" + port, r) } func handleXHR(w http.ResponseWriter, r *http.Request) { if r.FormValue("delay") == "1" { time.Sleep(100 * time.Millisecond) } response, _ := json.Marshal(WebResponse{time.Now()}) w.Write(response) } type WebResponse struct { Now time.Time `json:"now"` } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWS(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } writes := make(chan WSResponse) go respondWS(conn, writes) for { message := WSRequest{} err := conn.ReadJSON(&message) if err != nil { close(writes) return } go message.respond(writes) } } func respondWS(conn *websocket.Conn, writes chan WSResponse) { for { content, more := <-writes conn.WriteJSON(content) if !more { return } } } type WSRequest struct { Id int `json:id` Delay bool `json:delay` } func (request *WSRequest) respond( writes chan WSResponse) { if request.Delay { time.Sleep(100 * time.Millisecond) } response := WSResponse{time.Now(), request.Id} writes <- response } type WSResponse struct { Now time.Time `json:"now"` Id int `json:"id"` } Go Server
  • 44. What’s the score? • 88 lines of Go vs 39 lines of JavaScript! • JSON interaction was kind of clunky! • Haven’t figured out how to deploy to Heroku! • Doing what the cool kids are doing
  • 45. “ A straightforward translation of a C++ or Java program into Go is unlikely to produce a satisfactory result—Java programs are written in Java, not Go.” –Effective Go
  • 46. “ A straightforward translation of a C++ or Java JavaScript program into Go is unlikely to produce a satisfactory result —Java JavaScript programs are written in Java JavaScript, not Go.”
  • 47. John Maxwell john@agileleague.com @jmaxyz agileleague.com @agileleague