จาก Node.js ไป Go…

เมื่อไม่กี่เดือนที่แล้ว ผมได้ย้ายจาก Node.js มาใช้ Go ทำ Backend แทน เลยอยากมาแชร์ว่า Code ของ Node.js กับ Go หน้าตามันต่างกันยังไง


เริ่มจากดู code ง่าย ๆ อย่างการแสดงข้อความ

Go

package main
func main() {
println("Hello Go")
}

Node.js

console.log('Hello Node.js')

Error Handling ที่ต่างกัน…

Go

package main
import (
"errors"
"log"
)
func main() {
x, err := div(10, 0)
if err != nil {
log.Fatal(err)
}
log.Println("Result:", x)
}
func div(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("divide by zero")
}
return a / b, nil
}

Node.js

let x
try {
x = div(10, 0)
} catch (e) {
console.log(e)
process.exit(1)
}
console.log('Result:', x)
function div (a, b) {
if (b === 0) throw new Error('divide by zero')
return a / b
}

Object

Go

package main
import "log"
type Data struct {
Name string
Value int
}
func main() {
x := Data{"data_1", 15}
y := inc(x)
  log.Println("x:", x)
log.Println("y:", y)
}
func inc(data Data) Data {
data.Value++
return data
}

Node.js

let x = {
name: 'data_1',
value: 15
}
let y = inc(x)
console.log('x:', x)
console.log('y:', y)
function inc (data) {
return {
...data,
value: data.value + 1
}
}

Web Server

Go

package main
import (
"net/http"
  "github.com/gorilla/mux"
"github.com/urfave/negroni"
)
func main() {
n := negroni.New()
  r := mux.NewRouter()
r.Methods("GET").Path("/").HandlerFunc(Index)
  n.UseHandler(r)
n.Run(":8000")
}
func Index(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello from Go"))
}

Node.js

import express from 'express'
const app = express()
app.get('/', index)
app.listen('8000')
function index (req, res) {
res.end('Hello from Node.js')
}

ตัวอย่าง Backend แบบง่าย ๆ

Go

package main
import (
"encoding/json"
"net/http"
  "github.com/garyburd/redigo/redis"
"github.com/gorilla/mux"
"github.com/unrolled/render"
"github.com/urfave/negroni"
)
type Route struct {
Method string
Path string
HandlerFunc http.HandlerFunc
}
type PostData struct {
Data string `json:"data"`
}
var (
pool *redis.Pool
rr *render.Render
)
func main() {
pool = &redis.Pool{
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", ":6379")
},
}
rr = render.New()
n := negroni.New()
r := mux.NewRouter()
registerRoute(r)
n.UseHandler(r)
n.Run(":8000")
}
func registerRoute(router *mux.Router) {
rs := []Route{
Route{"GET", "/", listHandler},
Route{"POST", "/", insertHandler},
}
  for _, r := range rs {
router.
Methods(r.Method).
Path(r.Path).
HandlerFunc(r.HandlerFunc)
}
}
func listHandler(w http.ResponseWriter, r *http.Request) {
db := pool.Get()
defer db.Close()
  list, err := redis.Strings(db.Do("SMEMBERS", "list"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
rr.JSON(w, http.StatusOK, list)
}
func insertHandler(w http.ResponseWriter, r *http.Request) {
var obj PostData
if err := json.NewDecoder(r.Body).Decode(&obj); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
  db := pool.Get()
defer db.Close()
  _, err := db.Do("SADD", "list", obj.Data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
rr.Text(w, http.StatusOK, "ok")
}

Node.js

import express from 'express'
import Redis from 'ioredis'
import bodyParser from 'body-parser'
const app = express()
app.use(bodyParser.json())
const db = new Redis()
app.get('/', list)
app.post('/', insert)
app.listen('8000')
function list (req, res) {
db.smembers('list', (err, r) => {
if (err) return res.status(500).end(err.message)
res.json(r)
})
}
function insert (req, res) {
const obj = req.body
db.sadd('list', obj.data, (err) => {
if (err) return res.status(500).end(err.message)
res.end('ok')
})
}
Like what you read? Give acoshift a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.