لطفا صبر کنید ...

مقایسه زبان جاوا اسکریپت (Node.js) با زبان Go

الهام غایب

توسط الهام غایب

نویسنده
دیدگاه ها: 0
بازدید ها : 52
رایگان
هدف ما این است که شما، در بالاترین سطح طراحی و توسعه وب باشید.

ثبت نام کنید

در این مقاله از لیداوب به مقایسه بین سرورها و ساختارهای زبانی جاوا اسکریپت (Node.js) و Go پرداخته‌ایم.


گو (Go) یا گولنگ یک زبان برنامه نویسی متن باز است که توسط گوگل عرضه شده است. زبان برنامه نویسی گو جزو سریع‌ترین زبان‌های برنامه‌نویسی دنیاست و به سرعت به سوی سریعتر شدن حرکت می‌کند. در ابتدا، بایستی به این سوال پاسخ دهیم که آیا Go بهتر از جاوا اسکریپت است یا خیر؟ در جواب این سوال می‌توان گفت که هیچ‌کدام از آن‌ها برتری نسبت به یکدیگر ندارند. هر کدام از آن‌ها برای کار مشخصی مناسب است و گاهی یک ابزار از دیگری بهتر است یا یک برنامه نویس در استفاده از یک ابزار از برنامه نویس دیگری بهتر عمل می‌کند. بنابراین، هرچه می‌توانید یاد بگیرید و بهترین ابزاری که مطمئن هستید به بهترین شکل کار شما را انجام می‌دهد، انتخاب کنید. 

چرا از زبان برنامه نویسی Go استفاده می‌کنیم؟

از مهم‌ترین دلایل یادگیری زبان برنامه نویسی Go می‌توان به موارد زیر اشاره کرد:

- Go تنها دارای ۲۵ کلمه کلیدی است و این نشان می‌دهد که یادگیری این زبان چقدر آسان است.

- ما به الگوهای زبانی مشترک هم می‌پردازیم  و خواهیم دید وظایف مشترک در این زبان چقدر ساده‌تر و تمیزتر انجام می‌شود.

- کتابخانه استاندارد که با Go عرضه شده است دارای کاربردهای فراوانی است که دیگر نیازی به کتابخانه خارجی نخواهید داشت.

- کدهای Go در صورتی که شما دارای متغیرهای استفاده نشده یا خطاهای سینتکس باشید، کامپایل نخواهد شد.

در اینجا، مثالی از پکیج net/http را مشاهده می‌کنید:

مقایسه  Node.js با Go

 

مقایسه جاوا اسکریپت (Node.js) با زبان Go

ساختارهای زبانی

می‌خواهیم به چند ساختار زبانی که قبلا استفاده کرده‌ایم نگاهی بیاندازیم.

در اینجا کد Hello World در Node.js را مشاهده می‌کنید:

console.log('Hello World');

اجرای این کد Hello World را در ترمینال ایجاد می‌کند:

node app.js

در اینجا، معادل برنامه hello world را در زبان Go مشاهده می‌کنید:

package main

import "fmt"

func main() {
    fmt.Println("Hello World")
}

آنچه که در ابتدا مورد توجه قرار می‌گیرد این است که Go از یک ساختار مشخص پیروی می‌کند، این کد می‌تواند با تایپ کردن عبارت زیر یا دیدن آن در GoPlay Space اجرا شود:

go run main.go

که در آن، main.go نام فایل است.

انواع داده‌ ها، متغیرها و ثابت ها 

نوع داده‌ها در زبان جاوا اسکریپت به صورت داینامیک تعیین می‌شود یعنی شما در زمان تعریف متغیرها نیازی به مشخص کردن نوع آن ندارید و متغیرها می‌توانند نوع خود را به همراه برنامه تغییر دهند. با توجه به این موضوع، جاوا اسکریپت دارای انواع داده زیر است:

برای تعریف متغیرها در زبان جاوا اسکریپت (NodeJS) باید به صورت زیر  عمل کنیم:

const num = 3;
let flt = 2.34;
let a = true;
let b = false;
var name = 'Scotch';

البته در زبان Go انواع داده‌ها به صورت استاتیک تعیین می‌شوند یعنی ما ابتدا باید نوع را مشخص کرده و آن‌ها را به یک متغیر نسبت دهیم. یک معادل از تعاریف جاوا اسکریپتی بالا در زبان Go به صورت زیر است:

package main

const num = 3

func main() {
    var flt float64 = 2.34
    var name string = "Scotch"
    a, b := 2.34 // shorthand declaration syntax
}

تعیین مقادیر اولیه در Go از طریق عبارت کلیدی var، نام متغیر و یک نوع داده، انجام می‌شود. علاوه بر این، سینتکس کوتاه := هم قابل استفاده است. وقتی متغیرها با := تعریف شوند، به صورت خودکار نوع درست به آن‌ها اختصاص داده می‌شود. سینتکس خلاصه شده می‌تواند تنها در یک معادله به کار رود. در نهایت، شما می‌توانید چندین مقدار را در یک خط نسبت دهید مانند کاری که ما در a, b := true, false انجام دادیم. این کار باعث نسبت دادن a و b به مقادیر صحیح است. در اینجا، آرایه‌ای از رشته‌ها در جاوا اسکریپت را مشاهده می‌کنید:

const names = ['Scotch', 'IO'];

گرچه زبان Go دارای آرایه است، اما آنچه که ما در جاوا اسکریپت به عنوان آرایه می‌شناسیم، در Go به عنوان اسلایس یا تکه می‌شناسیم. در اینجا یک نمونه از اسلایس را در زبان Go مشاهده می‌کنید:

package main

func main() {
    names := []string{"Scotch", "IO"}
}

به عنوان مثال، ما یک برنامه کوچک می‌نویسیم که رشته فرعی یک رشته اصلی را در ایندکس ۱۰ بازگردانی کند. بنابراین، یک جمله مانند Luke, I’m not your father به این صورت به پایان می‌رسد: Luke, I’m

در زبان جاوا اسکریپت:

const sentence = '`Look, I\'m not your Father';`
console.log(sentence.substr(0,10));

در زبان Go:

package main

import "fmt"

func main() {
    sentence := "Look, I'm not your Father"
    fmt.Println(sentence[:10])
}

می‌توانید این اپلیکیشن را در Goplay Space اجرا کنید.

عبارات شرطی

عبارات شرطی شامل if else و switch است. در اینجا یک نمونه از node.js را مشاهده می‌کنید:

const age = 10;

if (age > 10) {
    console.log('You are old');
}

console.log('you are young');

const gender = 'female';

switch(gender) {
    case 'female':
        console.log('your name is tonie');
        break;
    case 'male':
        console.log('your name is tony');
        break;;
    default:
        ///
}

این هم معادل آن در زبان Go:

package main

import "fmt"

func main() {
    age := 10
    if age > 10 {
        fmt.Println("You are old")
    }
    fmt.Println("You are young")

    gender := "female"
    switch gender {
    case "female":
        fmt.Println("Your name is tonie ")
    case "male":
        fmt.Println("Your name is tony")
    default:
        ///
    }
}

می‌توانید این اپلیکیشن را در GoPlay Space اجرا کنید.

همانطور که مشاهده می‌کنید، شرط‌ها در زبان Golang کمی تمیزتر بوده و از براکت کمتری استفاده می‌کند.

حلقه ها

جاوا اسکریپت دارای سه نوع ساختار حلقه‌ای است،for loop ، while loop و do while loop . در اینجا یک نمونه از حلقه for loop را مشاهده می‌کنید:

// normal for loop
for i = 0; i < 10; i++ {
    console.log(i);
}

// key, value loop
for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + ' -> ' + p[key]);
    }
}

// another key value loop
Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
})

// there's also a `for...of`

Go فقط یک نوع حلقه دارد و آن هم for loop است. اما اجازه ندهید این موضوع شما را فریب دهد چون این حلقه بسیار همه کاره بوده و تقریبا عمل هر نوع حلقه‌ای را انجام می‌دهد. به این مثال ساده نگاه کنید:

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
    }

    // key value pairs
    kvs := map[string]string{
        "name":    "Scotch",
        "website": "https://scotch.io",
    }

    for key, value := range kvs {
        fmt.Println(key, value)
    }
}

می‌توانید این اپلیکیشن را در GoPlay Space اجرا کنید.

سرور Http

حالا که کمی در مورد شباهت‌ها و تفاوت‌های ساختار زبانی جاوا اسکریپت و گولنگ دانستیم، می‌توانیم نگاهی هم به سرورها بیاندازیم. از آنجایی که ما از node.js می‌آییم، این احتمال وجود دارد که سروری ایجاد کنیم که مقادیر JSON بازگرداند. خوشبختانه، در node.js وقتی سروری را می‌نویسیم از Express به عنوان کتابخانه پایه سرور استفاده می‌کنیم. در اینجا یک نمونه سرور node.js مشاهده می‌کنید:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello from Express!');
})

app.listen(3000, err => {
  if (err) {
    return console.log('something bad happened', err);
  }

  console.log(`server is listening on 3000`);
})

بر خلاف جاوا اسکریپت، کتابخانه استاندارد Go هر آنچه که برای راه اندازی سرور نیاز داریم را بدون نیاز به وابستگی خارجی، در اختیار ما قرار می‌دهد. پکیج net/http بیشتر این کارایی‌ها را ادامه می‌دهد. در هنگام ساخت اپلیکیشن‌های بزرگ‌تر، استفاده از پکیج net/http با پکیج‌های خارجی رایج است و یک کتابخانه محبوب که امکانات زیادی در اختیار برنامه نویس قرار می‌دهد Gorilla Web Toolkit است. در اینجا یک نمونه سرور Go معادل سرور node مشاهده می‌کنید که هیچ کتابخانه خارجی ندارد:

package main

import (
    "net/http"
)

func Hello(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello World"))
}
func main() {
    http.HandleFunc("/", Hello)
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

حالا جالب‌تر هم می‌شود:

if err != nil {
    // do something here
    // return err or panic
    panic(err)
}

شما می‌توانید این کار را با اجرای go run main.go تست کنید، با فرض این که نام فایل شما main.go باشد.

حالا می‌خواهیم یک کتابخانه روتر معرفی کنیم:

if req.Method == "POST" {
    // do this
}

برای دریافت پکیج‌های زبان golang، معمولا از go get <github-link> استفاده می‌کنیم. برای دریافت Gorilla  Mux از Gorilla Web Toolkit کد زیر را در ترمینال خود تایپ می‌کنیم:

go get -u github.com/gorilla/mux

سپس، می‌توانیم این کار را انجام دهیم:

package main

import (
     "fmt"
     "net/http"

     "github.com/gorilla/mux"
)
func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", HomeHandler)
    r.HandleFunc("/products", ProductsHandler)
    r.HandleFunc("/articles", ArticlesHandler)

    // details
    r.HandleFunc("/products/{key}", ProductHandler)
    r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
    r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)

    http.Handle("/", r)
}

// example handler
func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, "Category: %v\n", vars["category"])
}

مشاهده می‌کنید که Gorilla mux به ما اجازه داد تا از الگوهای مشابه استفاده کنیم اما کمی پیچیده می‌شود. Gorilla mux دارای توابع کمکی یا helper هم هست.

مطالعه مقالات بیشتر در لیداوب:

استفاده از Middleware

Middleware‌ها بخش فوق‌العاده و مهمی از سرورهای node.js هستند. آن‌ها توابعی هستند که در جایی قرار گرفته و قبل از آنکه درخواست اصلی اجرا شود، اجرا می‌شوند. در node.js این یک تکه کد ساده برای یک middleware است که یک رمز از env دریافت کرده و آن را برای تایید هویت کاربر استفاده می‌کند. در زمان خواندن متغیرها از node.js، معمولا از dotenv استفاده می‌شود:

const express = require('express');
const app = express();

// add server_name middleware
function authenticate((req, res, next) => {
    const secret = process.ENV.SECRET;
    if (secret == "") {
        return res.send("secret not found");
    }

    if (!isAuthenticated(req, secret)) {
        return res.send("invalid authentication");
    }

    return next();
})

app.get('/', authenticate, (req, res) => {
  res.send('Hello from Express!');
})

app.listen(3000, err => {
  if (err) {
    return console.log('something bad happened', err);
  }

  console.log(`server is listening on 3000`);
})

Go دارای روش ساده‌تری برای این کار است. چون تمام کاری که یک middleware انجام می‌دهد گرفتن درخواست، انجام کاری در مورد آن و تصمیم گیری در مورد این است که آیا درخواست باید پردازش شود یا خیر:

package main

import (
    "net/http"
    "os"
)

// our sample authenticate middleware
func Authenticate(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r _http.Request) {
        secret := os.Getenv('SECRET')
        if len(secret) == 0 {
            w.Write(_[_]byte("secret not found")
            return
        }

        if !isAuthenticated(r, secret) {
            w.Write(_[_]byte("invalid authentication"))
            return
        }
        next.ServeHTTP(w, r)
    }

func Hello(w http.ResponseWriter, r _http.Request) {
    w.Write([]byte("Hello World"))
}

func main() {
    http.HandleFunc("/", Authenticate(Hello)) // call the middeware by wrapping
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

اگر شما یک برنامه نویس حرفه‌ای جاوا اسکریپت باشید، احتمالا متوجه توابعی که در Go هم به کار رفته‌اند شده‌اید. ما فقط تابعی را می‌نویسیم که یک [http.HandlerFunc](https://golang.org/pkg/net/http/#HandlerFunc) را می‌پذیرد که یک function type است و ساختار تابع هم type HandlerFunc func(ResponseWriter, *Request) است، درست مانند Hndler که ما نوشتیم.

مزیت آن در این است که نوع http.HandlerFunc دارای یک تابع ServerHTTP می‌باشد که پاسخ و درخواستی که ما ارسال کرده‌ایم را بر عهده می‌گیرد و فراخوانی را اجرا می‌کند. بعضی از افراد این روش را wrapping functions می‌نامند اما این یک ایده کلی است. شما می‌توانید middleware‌های خود را بنویسید اما کتابخانه‌هایی مانند موارد زیر به کمک شما می‌آیند:

استفاده از API

در اکثر موارد، سرورهای ما معمولا به یک API خارجی وابسته هستند تا داده‌هایی که لازم دارند را دریافت کنند. مثلا کاربران را از Github دریافت می‌کنند. این روش در node.js انجام می‌شود. ابتدا یک ماژول درخواست http مانند axios با دستور   npm install axios نصب می‌کنید:

const axios = require('axios');
const url = 'https://api.github.com/users';

axios.get(url).then(res => {
    // do something with the response
}).catch(err => {
    // do something with the error
})

این تکه کد می‌تواند در سرویس شما یا هر جایی که بخواهید باشد. البته، در Go نیازی به هیچ وابستگی خارجی نداریم و پکیج net/http می‌تواند به ما کمک کند:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func main() {
    URL := "https://api.github.com/users"
    res, err := http.Get(URL)
    if err != nil {
        log.Println(err)
    }
    defer res.Body.Close() // for garbage collection

    responseBodyBytes, err := ioutil.ReadAll(res.Body)
    if err != nil {
        log.Println(err)
    }

    fmt.Println(string(responseBodyBytes))
}

ما از http.get برای ایجاد درخواست و بررسی خطاها استفاده می‌کنیم. پاسخ معمولا به صورت بایت برگردانده می‌شود و ما ابتدا باید آن را خوانده و سپس آن را به رشته‌ای با string([]bytes) تبدیل کنیم. شما می‌توانید این را به یک فایل main.go اضافه کرده و go run main.go را اجرا کنید. این کد می‌تواند به راحتی به یک تابع تبدیل شود و در زمان نیاز مجددا فراخوانی شود.

کانکشن‌های دیتابیس

Node.js دارای ماژول‌های متعدد npm برای کمک به کانکشن‌های دیتابیس است که بستگی به دیتابیسی که شما استفاده می‌کنید دارد. این کتابخانه‌ها بیشتر اوقات متدهای منحصر به فرد خود را دارند که کار کردن با آن‌ها را ساده‌تر می‌کند و برخی از آن‌ها هم ویژگی‌های مشابه با ORM ارائه می‌دهند.

اما Go روش متفاوتی را انتخاب می‌کند. این کتابخانه استاندارد یک رابط کاربری برای کار با دیتابیس‌ ارائه می‌کند که https://golang.org/pkg/database/sql/ نام دارد که طراح پکیج‌ RDBMS می‌تواند از آن برای پیاده سازی درایو برای دیتابیس‌های مختلف استفاده کند. طراحانی که از این رابط استاندارد استفاده می‌کنند، می‌توانند مطمئن شوند که این رابط برای پکیج‌های مختلف کارایی دارد.

Go با استفاده از https://github.com/jmoiron/sqlx کارایی را بالا می‌برد. Go نه تنها از ORM کنار گذاشته نمی‌شود، بلکه orm‌های فوق العاده‌ای برای https://github.com/jinzhu/gorm در آن نوشته شده است.

نتیجه گیری

فایل‌های Go باید درون پکیج‌ها نوشته شوند و این معمولا ساختار فایل شما را تحت تاثیر قرار می‌دهد. در جاوا اسکریپت، شما تعداد زیادی عبارت require در ابتدای فایل‌ها مشاهده می‌کنید در حالی که در زبان Golang، اولین خط همیشه نام یک پکیج است که به عنوان مسیر import در فایل که به import package_path/package_name نیاز است، استفاده می‌شود. امیدواریم با مطالعه این مقاله در لیداوب توانسته باشید یک دید کلی از تفاوت میان node.js و Go به دست آورید.

5 از 1 رای

 مطالب مرتبط  

در قسمت زیر مطالبی وجود دارند که با مقاله فعلی مرتبط هستند

متاسفانه فقط اعضای سایت قادر به ثبت دیدگاه هستند

برترین های