Will Node.js forever be the sluggish Golang?

Will Node.js forever be the sluggish Golang?

It seems you cannot go a week without hearing about the next, allegedly faster, so called “web framework” for Node.js. Yes we all know Express is slow, but can yet another “web framework” really&nbsp;<em>improve</em>&nbsp;I/O performance? Beyond evading the overhead of Express, no, it cannot. To reach further you need to dig deep and redesign, not just slap a new layer on top.

It seems you cannot go a week without hearing about the next, allegedly faster, so called “web framework” for Node.js. Yes we all know Express is slow, but can yet another “web framework” really improve I/O performance? Beyond evading the overhead of Express, no, it cannot. To reach further you need to dig deep and redesign, not just slap a new layer on top.


Express is one of the oldest, so called “web framework” for Node.js. It builds on the out-of-box features Node.js provide, adding a nice App-centered programming interface to manage URL routes, parameters, methods and the like.

It is productive and elegant, sure, but lacks in performance. Emerging are projects like Fastify, and hundreds alike. They all aim to provide what Express does, at a lower performance penalty. But that’s exactly what they are; a penalty. Not an improvement. They’re still strictly limited to what Node.js can provide, and that’s not much as compared to the competition:

No so called “web framework” for Node.js, whether Fastify or not, can surpass the red line. This is a pretty low upper limit as compared to trending alternatives like Golang.

Luckily Node.js supports C++ addons, Google V8 bindings that link JavaScript to C++ and allows your JavaScript to invoke any behavior, even behavior that’s not provided by Node.js itself.

This makes it possible to extend and redefine what’s possible to do with JavaScript. It opens up for JavaScript that performs to the full extent made possible by Google V8, not limited to what the Node.js “core programmers” have decided is good enough.

Releasing the new µWebSockets.js

I’m releasing brand new code, µWebSockets.js, available on GitHub today:

https://github.com/uNetworking/uWebSockets.js

  • Install for Node.js using NPM (although hosted on GitHub):
  • npm install uNetworking/uWebSockets.js#v15.0.0 , see NPM install docs.
  • No compiler needed; Linux, macOS and Windows. We start at version 15.0.0 and increment according to SemVer.

It’s an alternative web server for JavaScript backends, written in ~6 thousand lines of C and C++, surpassing in performance the best of Golang by a large margin. Bitfinex.com already ported both of their trading APIs (REST & WebSocket) and are currently gradually putting it in production.

Paolo Ardoino from Bitfinex wanted to interject that “it’s a damn pretty cool project”.
This work is made possible solely thanks to sponsors; BitMEX, Bitfinex and Coinbase have made this work possible. Thanks to them, we now have a new release!

Please explain, what’s this all about?

This is a new project, new code licensed Apache 2.0, successor to what’s known as “uws”. It’s an entire stack, from OS kernel to Google V8, a complete bypass that brings stable, secure, standards-compliant, fast and lightweight I/O for Node.js:


In this layered software design, where every layer depend only on the previous one, it becomes very easy to track and fix issues and/or extend with new support.

µSockets itself even has three sub layers, going from eventing to networking to crypto, each sub layer only aware of the previous one. This makes it possible to swap out parts, fix bugs, add alternative implementations all without changing any high level code.

Feeling tired of OpenSSL? Fine, swap it out by replacing ssl.c and its 600 lines of code. No other layer even knows what SSL is, so bugs are easy to locate.

Internal sub layers of µSockets

This differs greatly from how Node.js is implemented, with its “all-and-everything-in-one” design. In one source file of Node.js you can find libuv calls, syscalls, OpenSSL calls, V8 calls. It’s all mixed up in a big mess with no sense of isolated purpose. This makes it hard to make any real change.

Coding for µWebSockets.js, in a nutshell

Following is an oversimplification, many concepts left out for brevity, but should give you an idea of what µWebSockets.js is all about:


It is possible to outperform, in some regards, Golang’s Gorilla WebSockets on an SSL vs. non-SSL basis. That is, your JS code on SSL can message faster than Golang can without SSL (in some regards). I think that’s pretty cool.

Fast pub/sub support

Socket.IO is in many ways the “real-time” equivalent of Express. Both are old, elegant and popular, but also very slow:


Most of what Socket.IO helps you with boils down to pub/sub, the feature to emit messages to a room of multiple recipients, and to receive likewise.

Fallbacks are completely pointless today as every browser supports, and has supported for ages, WebSockets. SSL traffic cannot be interpreted by corporate proxies, and will pass through just like any Http traffic would, so WebSockets over SSL is definitely not going to be blocked. You can still have fallbacks, but they are pointless and incur unnecessary complexity.

One goal with µWebSockets.js is to provide features similar to those found in Socket.IO to make it somewhat simple to swap away completely, without any wrapper on top. This while not enforcing any particular non-standard protocol.

Many companies, most of them, struggle with some kind of pub/sub problem when it comes to WebSockets. Sadly, efficient pub/sub did not make the deadline for this release, but is coming shortly. Very high priority. It’s going to be really fast (benchmarks already put it faster than Redis). Keep an eye out!

What happens now?

Polishing, adding features and correcting mistakes. There’s going to be a period of introduction where things will maybe not fit in completely from the start. Keep in mind, it’s a large project consisting of many thousands of lines of C++ and C in three different repositories:


This project is used by companies with huge stress on I/O. Stability and security is (naturally & obviously) of highest priority to the project. Make sure to report stability issues in early point-releases now that this code is a major and big release with tons of changes.


Top 7 Most Popular Node.js Frameworks You Should Know

Top 7 Most Popular Node.js Frameworks You Should Know

Node.js is an open-source, cross-platform, runtime environment that allows developers to run JavaScript outside of a browser. In this post, you'll see top 7 of the most popular Node frameworks at this point in time (ranked from high to low by GitHub stars).

Node.js is an open-source, cross-platform, runtime environment that allows developers to run JavaScript outside of a browser.

One of the main advantages of Node is that it enables developers to use JavaScript on both the front-end and the back-end of an application. This not only makes the source code of any app cleaner and more consistent, but it significantly speeds up app development too, as developers only need to use one language.

Node is fast, scalable, and easy to get started with. Its default package manager is npm, which means it also sports the largest ecosystem of open-source libraries. Node is used by companies such as NASA, Uber, Netflix, and Walmart.

But Node doesn't come alone. It comes with a plethora of frameworks. A Node framework can be pictured as the external scaffolding that you can build your app in. These frameworks are built on top of Node and extend the technology's functionality, mostly by making apps easier to prototype and develop, while also making them faster and more scalable.

Below are 7of the most popular Node frameworks at this point in time (ranked from high to low by GitHub stars).

Express

With over 43,000 GitHub stars, Express is the most popular Node framework. It brands itself as a fast, unopinionated, and minimalist framework. Express acts as middleware: it helps set up and configure routes to send and receive requests between the front-end and the database of an app.

Express provides lightweight, powerful tools for HTTP servers. It's a great framework for single-page apps, websites, hybrids, or public HTTP APIs. It supports over fourteen different template engines, so developers aren't forced into any specific ORM.

Meteor

Meteor is a full-stack JavaScript platform. It allows developers to build real-time web apps, i.e. apps where code changes are pushed to all browsers and devices in real-time. Additionally, servers send data over the wire, instead of HTML. The client renders the data.

The project has over 41,000 GitHub stars and is built to power large projects. Meteor is used by companies such as Mazda, Honeywell, Qualcomm, and IKEA. It has excellent documentation and a strong community behind it.

Koa

Koa is built by the same team that built Express. It uses ES6 methods that allow developers to work without callbacks. Developers also have more control over error-handling. Koa has no middleware within its core, which means that developers have more control over configuration, but which means that traditional Node middleware (e.g. req, res, next) won't work with Koa.

Koa already has over 26,000 GitHub stars. The Express developers built Koa because they wanted a lighter framework that was more expressive and more robust than Express. You can find out more about the differences between Koa and Express here.

Sails

Sails is a real-time, MVC framework for Node that's built on Express. It supports auto-generated REST APIs and comes with an easy WebSocket integration.

The project has over 20,000 stars on GitHub and is compatible with almost all databases (MySQL, MongoDB, PostgreSQL, Redis). It's also compatible with most front-end technologies (Angular, iOS, Android, React, and even Windows Phone).

Nest

Nest has over 15,000 GitHub stars. It uses progressive JavaScript and is built with TypeScript, which means it comes with strong typing. It combines elements of object-oriented programming, functional programming, and functional reactive programming.

Nest is packaged in such a way it serves as a complete development kit for writing enterprise-level apps. The framework uses Express, but is compatible with a wide range of other libraries.

LoopBack

LoopBack is a framework that allows developers to quickly create REST APIs. It has an easy-to-use CLI wizard and allows developers to create models either on their schema or dynamically. It also has a built-in API explorer.

LoopBack has over 12,000 GitHub stars and is used by companies such as GoDaddy, Symantec, and the Bank of America. It's compatible with many REST services and a wide variety of databases (MongoDB, Oracle, MySQL, PostgreSQL).

Hapi

Similar to Express, hapi serves data by intermediating between server-side and client-side. As such, it's can serve as a substitute for Express. Hapi allows developers to focus on writing reusable app logic in a modular and prescriptive fashion.

The project has over 11,000 GitHub stars. It has built-in support for input validation, caching, authentication, and more. Hapi was originally developed to handle all of Walmart's mobile traffic during Black Friday.

Google’s Go Essentials For Node.js / JavaScript Developers

Google’s Go Essentials For Node.js / JavaScript Developers

Keep checking this article as I will make it more comparative between Go and Node constructs. This article will be a brain dump of all I’ve learned so far about Google’s Go language.

Keep checking this article as I will make it more comparative between Go and Node constructs. This article will be a brain dump of all I’ve learned so far about Google’s Go language.

As an advanced JavaScript developer, The more I work with JavaScript the more I understand the advantages of a statically typed language.

Paradoxically, it is easier to make TypeErrors in JavaScript than in other languages I have used. When you do work on the back-end, it is unacceptable. On the front end, when you are a little bit serious about your work, you notice how so many JS developer do NOT understand the typing system in JavaScript because it is not forced on them. That’s why there is a lot of garbage JS code in the world.

JavaScript is HARD when you get serious about understanding it under the hood. So many (kind of hidden) complex concepts you have to understand in order to make sense of the errors in your code (or why it’s working but that’s not the correct way to do it…).

JavaScript is fascinating but sometimes you want to try something else and broaden your horizon.

This article will be a brain dump of all I’ve learned so far about Google’s Go language.

I assume you have installed the Go binaries on your computer.

Variables

package main

import "fmt"

func main() {
    // you MUST use a declared variable otherwise compilation error
    
    var toto int8 = 123
    fmt.Println(toto)

    var tito = 123
    fmt.Println(tito)

    // variable declaration with type inference
    toti := 123
    fmt.Println(toti)

    // variable declaration (implicitly initialized to zero-value,// for numeric types = 0)
    var tata int
    fmt.Println(tata)

    // variable assignment
    tata = 951
    fmt.Println(tata)
}

Number Types

package main

import "fmt"

func main() {
    // Go does not convert types automatically
    // need to explicitly convert them
    var (
        i int8    = 20
        f float32 = 5.6
    )
    fmt.Println(i + int8(f+1.9))

    var (
        j int32 = 456
        k int64 = 987654
    )
    fmt.Println(int64(j) + k)

    // byte is an alias for uint8
    // no need to convert uint8 to byte because same
    var (
        l byte  = 123
        m uint8 = 45
    )
    fmt.Println(l + m)

    // int is an alias for int32 or int64, // dedpending on your mqchine's integer value
    var (
        n int32 = 324
        o int   = 84529899
    )
    fmt.Println(int(n) + o)

    // uint is an alias for uint32 or int64
    var (
        p uint   = 999
        q uint64 = 9999
    )
    fmt.Println(p + uint(q))

    // float operations do not produce an exact result after n decimals// like in most languages
    myFloat := 1.000
    myFloat2 := .999
    fmt.Println(myFloat - myFloat2)

    // arithmetic operations
    fmt.Printf("%d + %d = %d \n", 25, 39, 25+39)
    fmt.Printf("%d - %d = %d \n", 25, 39, 25-39)
    fmt.Printf("%d * %d = %d \n", 25, 39, 25*39)
    fmt.Printf("%d / %d = %v \n", 25, 39, 25/39)
    fmt.Printf("%d %% %d = %v \n", 25, 39, 25%39)

    // constants
    const goldenRatio float64 = 1.6180327868852
    fmt.Printf("The golden ration approximately %f \n", goldenRatio)
    fmt.Printf("The ration truncated to the 3rd decimal is %.3f \n", goldenRatio)

    // formatted printing for numeric types
    fmt.Printf("decimal is %d \n", 99)
    fmt.Printf("binary is %b \n", 99)
    fmt.Printf("unicode reference is %c \n", 99)
    fmt.Printf("hexadecimal is %x \n", 99)
    fmt.Printf("scientific notation of goldenRatio is %e \n", goldenRatio)
}

String Types

package main

import "fmt"

func main() {
    // zero-value for strings is an empty string ""
    var str string
    fmt.Println("\"" + str + "\"")

    str = "This is a string."
    fmt.Println(str)

    str2 := "Another string."
    fmt.Println(str2)

    // raw string literalss with back ticks
    // can be written on multiple lines and no escapes
    str3 := `
        Raw string in the building.
        And another line.
    `
    fmt.Println(str3)

    str4 := "Dunya nzuri = "
    str5 := "美麗的世界"
    str6 := str4 + str5
    fmt.Println(str6)

    // In Go, strings are immutable sequences of bytes
    // you can access each byte
    str7 := "mazoezi"
    b1 := str7[0]
    b2 := str7[1]
    fmt.Println(str7, "\n\t", b1, "=", string(b1), b2, "=", string(b2))

    // substrings
    s1 := str7[0:2]
    s2 := str7[2:4]
    s3 := str7[:3]
    s4 := str7[3:]
    fmt.Printf("%s \t %s \t %s \t %s \n", s1, s2, s3, s4)

    // length of string
    fmt.Println(str7, " = ", len(str7), " characters")

    // single character = rune -> numeric type, sane as int32
    // can be converted to a string
    var r rune 
    // single qutoes
    r = '✖'         // same as r = 10006
    fmt.Println("This is a rune : ", r, " which in string = ", string(r))
}

If and For Statements

package main

import "fmt"

func main() {
    a := 27

    // no parentheses surrounding the condition
    // the body of the if statement MUST be surrounded with {} // no matter what
    // no truthy values
    if a > 25 {
        fmt.Println("a is greater than 25")
    } else {
        fmt.Println("a is less than 25")
    }

    b := 546

    // if statement have block scope
    if b == 546 {
        // c does not exist outside of the if
        c := 54
        fmt.Println(b + c)
    }

    // can declare a variable available ONLY in if and else block
    if d := 44; b < 25 {
        fmt.Println("a is greater than 25", d)
    } else {
        fmt.Println("a is less than 25", d)
    }

    // for loop, no parentheses around signature
    e := 2
    for index := 0; index < 10; index++ {
        if index+e == 2 {
            continue
        }
        if index > 8 {
            break
        }
        fmt.Println("index =", index)

    }

    // equivalent of while statement
    f := 0
    for f < 6 {
        fmt.Println("f =", f)
        // don't forget to have smth allowing to get out of the loop
        f++
    }

    // infinite loop
    g := 0
    for {
        fmt.Println("g =", g)
        g++
        // to stop it at some point
        if g > 30 {
            break
        }
    }

    // for range loop
    
    h := "this is great!"
    for k, v := range h {
        fmt.Println("offset (position) =",k,", value as rune =", v, ",value as string = ", string(v))
    }

    // logical operators
    fmt.Printf("%t && %t is %t \n", true, false, true && false)
    fmt.Printf("%t || %t is %t \n", true, false, true || false)
    fmt.Printf("!%t is %t \n", true, !true) 
}

Functions

package main

import "fmt"

func main() {
    addNumbers(353454, 99999)
    addNumbers(353, 9999)
    addNumbers(3554, 99)

    a := addInts(99, 1)
    fmt.Println("a = ", a)

    a = addInts(9, 675)
    fmt.Println("a = ", a)

    div, remainder := divAndRemainder(57, 7)
    fmt.Println(div, remainder)

    // use underscore to ignore a returned value
    div, _ = divAndRemainder(57, 7)
    fmt.Println(div)

    _, remainder = divAndRemainder(57, 7)
    fmt.Println(remainder)

    divAndRemainder(57, 7)

    // in Go, all functions calls are done by value// (exceptions, see later)
    // a copy of input argument variables is passed o the function
    y := 5
    arr := [2]int{45, 99}
    s := "olo"
    doubleFail(y, arr, s)
    fmt.Println("outside doublefail", y, arr, s)
}

// where function is placed does not matter
// no overloading of function w/ different input parameters
func addNumbers(a int, b int) {
    fmt.Println(a + b)
}

func addInts(c int, d int) int {
    return c + d
}

// multiple returns
func divAndRemainder(e int, f int) (int, int) {
    return e / f, e%f
}

func doubleFail(a int, arr [2]int, s string)  {
    a = a * 2
    for index := 0; index < len(arr); index++ {
        arr[index] *= 2
    }
    s = s + s
    fmt.Println("in doublefail", a, arr, s)
}

Pointers

// pointers are used in C to simulate arrays and strings
package main

import "fmt"

// pointer as input parameter
func setTo10(pointerToInt *int) {
    *pointerToInt = 10
}

func setTo10Fail(pointerToInt *int) {
    fmt.Println("#setTo!(Fail pointer passed as argument =", pointerToInt)
    // will not affect the original pointer because passed by value
    pointerToInt = new(int)
    fmt.Println("#setTo!(Fail reassignment =", pointerToInt)

    // set the value in memory to 10
    *pointerToInt = 10
}

func main() {
    a := 10
    // & = reference / pointer to variable "a"
    // the value of b is the location where a is stored
    b := &a
    // c is a copy of "a" at a given time, // they are independent of each other after the first assignment
    c := a
    fmt.Println(a, b, *b, c)

    a = 20
    // to see the value inside the memory location use * // (de-reference the pointer and get to the value)
    fmt.Println(a, b, *b, c)

    // dereference the pointer and assign a value in memory
    // therefore the value of "a" also changes
    *b = 30
    fmt.Println(a, b, *b, c)

    c = 40
    fmt.Println(a, b, *b, c)

    // zero-value for a pointer is nil (absence of value)
    var d *int
    fmt.Println("value of d =", d)
    // cannot read or write value of a nil pointer
    // fmt.Println(*d)   // throws a panic

    e := new(int)
    // new keyword makes a pointer for the type
    fmt.Println("pointer to e =", e)
    // new also allocates memory, here to the zero-value forint type// therefore no panic
    fmt.Println("value of e =", *e)

    f := 20
    fmt.Println("value of f =", f)
    // we pass a pointer to f into that function
    setTo10(&f)
    fmt.Println("value of f after setTo10 =", f)

    g := 30
    fmt.Println("pointer to g =", &g)
    fmt.Println("value of g =", g)
    // on Go, variable in function calls are passed by VALUE
    setTo10Fail(&g)
    fmt.Println("pointer to g after #setTo10Fail =", &g)
    // you CANNOT change the pointer of a variable passed
    fmt.Println("value of g after #setTo10Fail =", g)
}

Arrays

package main

import "fmt"

func main() {
    // zero-value of arrays is an array// of specified length of zero-values of the type inside the array
    var myArrInt [4]int
    fmt.Println(myArrInt)

    myArrInt[0] = 12
    myArrInt[1] = 23
    myArrInt[2] = 34
    myArrInt[3] = 45
    fmt.Println(myArrInt)

    // one-line array assihnement in a composite literal expression
    // the length of the array is part of its type definition
    myArrInt = [4]int{111, 222, 333, 444}
    fmt.Println(myArrInt)

    myArrStr := [4]string{"titi", "tooi", "tatu", "teti"}
    fmt.Println(myArrStr)

    // iterate over an array
    for i, val := range myArrInt {
        fmt.Printf("At index %d = %d \n", i, val)
    }

    // slice of an array
    myArrStr2 := myArrStr[:2]

    // use _ to ignore the index variable
    for _, val := range myArrStr2 {
        fmt.Println(val)
    }
    // use of arrays is limited, slices are more flexible

}

Slices and Maps

package main

import "fmt"

func main() {
    /*
      SLICE = growable sequence of values of a single specified type
      the size is not part of the type definition
    */
    // define a slice in a composite literal expression
    myFiboSlice := []int{0, 1, 2, 3, 5, 8, 13}
    fmt.Println("myFiboSlice is", myFiboSlice)

    // create a slice from another slice = slice expression
    myFiboSlice2 := myFiboSlice[1:4]
    fmt.Println("myFiboSlice2 is", myFiboSlice2)

    // carefully with subslices because// they point to the same location in memory as the original slice
    myFiboSlice[2] = 00
    fmt.Println("\n myFiboSlice is", myFiboSlice)
    // slices are reference types, behave like pointers
    fmt.Println("myFiboSlice2 after modifying myFiboSlice is", myFiboSlice2)

    // zero-value for slice is nil slice (no value in slice)
    titiSlice := []string{"titi_one", "titi_two", "titi_three"}
    var totoSlice []string
    fmt.Println("totoSlice is", totoSlice)
    fmt.Println("length of totoSlice is", len(totoSlice))

    // assigning slice to another slice makes them share same location// in memrory
    totoSlice = titiSlice
    fmt.Println("totoSlice is now", totoSlice)
    titiSlice[0] = "titi_zero"
    fmt.Println("after modifying titiSlice, totoSlice is now", totoSlice)

    // this behavior also happens in functions
    modifySlice(titiSlice)
    fmt.Println("after modifying titiSlice in a function, totoSlice is now", totoSlice)

    // define a slice filled with wero-values of the type specified
    // last argument is the capacity of the underlying array
    s1 := make([]int, 5, 20)

    // copy a slice from another slice with the copy built-in function// "copy in slice s1 the elements of slice myFiboSlice
    copy(s1, myFiboSlice) 
    fmt.Println("\ns1 is", s1)

    // append built-in function -> returns a new slice
    // increases the length of the slice
    s2 := append(s1, 21, 34, 55)
    fmt.Println("s2 is", s2)

    // append a slice to another slice
    s3 := []int{111, 222, 333}
    // notice the ... after the s3 identier to spread the elements in it
    s3 = append(s2, s3...)
    fmt.Println("s3 is", s3)

    // deleting element at offset 6 (7th) from slice (the easy way)
    s3 = append(s3[:6], s3[7:]...)
    fmt.Println("s3 is", s3)

    // deleting from slice, the more involved way (see the function below)// it was tough to find a working algorithm !
    s3 = deleteItemFromSliceAtIndex(s3, 3)
    fmt.Println("s3 is", s3)

    // slices are based on an underlying array // for which you can specify the capacity // (number of spots to allocate in memory)
    // here the slice is initialized with 5 zero-value spots // but the underlying array has 100 spots in case we append.
    // This allows to avoid to copy and create a new underlying array // every time we append more than the length of the slice
    s4 := make([]int, 5, 100)
    fmt.Println("s4 is", s4)
    fmt.Println("length of s4 is", len(s4))
    fmt.Println("capacity of s4 is", cap(s4))

    // make a slice of bytes out of a string
    hello := "李先生你好"
    myByteSlice := []byte(hello)
    fmt.Println("\nmyByteSlice is", myByteSlice)

    myRuneSlice := []rune(hello)
    fmt.Println("\nmyRuneSlice is", myRuneSlice)

    // multidimensional slice
    s5 := []int{84, 64, 44}
    s6 := []int{42, 32, 22}
    s7 := [][]int{s5, s6}
    fmt.Println("\ns7 is", s7)

    /********** MAPS ****************/

    // associate value of single data type to value of another data type// collection of key / value pairs (key not restricted to a string)
    // maps are unordered

    myMap := make(map[string]string)
    myMap["name"] = "GOTO"
    myMap["firstname"] = "Florian"
    myMap["occupation"] = "Software Engineer"
    myMap["native_language"] = "French"
    fmt.Printf("\n%v\n", myMap)

    // access value in map
    fmt.Printf("The name is %v\n", myMap["name"])

    // if no value on a key return zero-value for the type of value
    fmt.Printf("The age is %v\n", myMap["age"])

    // make sure a key is in the map = comma ok idiom
    // v = value associated w/ existing key
    // ok = boolean is key in map
    if v, ok := myMap["isBillionaire"]; ok {
        fmt.Println("isBillionaire in map =", v)
    } else {
        // ok == false
        fmt.Println("isBillionaire in map =", ok)
    }

    // map literal declaration (composite literal expression)
    worldMap := map[int]string{
        // every line must end with a comma
        1: "nimefurahi kukuona",
        2: "приємно бачити вас",
        3: "तुम्हें देखकर अच्छा लगा",
        4: "ስለተያየን ደስ ብሎኛል",
        5: "ดีใจที่ได้พบคุณ",
    }

    // iterate over a map - order of iteration is random
    for keyInMap, valueInMap := range worldMap {
        fmt.Println(keyInMap, "=", valueInMap)
    }

    // delete value from map (built-in function)
    delete(worldMap, 2)
    fmt.Println("worldMap :", worldMap)

    // same as slices, maps are passed by reference

    // nil map
    var tMap map[string]int
    // writing to zero-valued map will make the program panic
    // tMap["toto"] = 12345678
    fmt.Println("tMap :", tMap)
    fmt.Println("length of tMap :", len(tMap))

    // delete an element in map
    sport := map[string]string{"yoyo": "ok", "ping pong": "great"}
    fmt.Println("sport :", sport)
    delete(sport, "yoyo")
    fmt.Println("sport :", sport)

    // to make sure that you delete an existing pair in the map
    langs := map[string]string{
        "ES6+":         "great",
        "Go":           "cool",
        "TypeScript":   "ok",
        "Python":       "over hyped but nice",
        "Bash":         "necessary",
        "HTML5":        "necessary",
        "CSS":          "necessary",
        "Elm":          "niche",
        "Java":         "no comments...",
        "Rust":         "to assess",
        "Web Assembly": "who knows",
    }
    fmt.Println("lang :", langs)
    if _, ok := langs["assembly"]; ok {
        delete(langs, "assembly")
    }
    fmt.Println("lang :", langs)

}

func modifySlice(s []string) {
    s[1] = "one"
    fmt.Println("\n", s)
}

func deleteItemFromSliceAtIndex(s []int, index int) []int {
    temp := make(map[int]int, len(s))
    // convert slice to map
    for i, v := range s {
        if i == index {
            continue
        }
        temp[i] = v
    }

    newSlice := make([]int, len(temp))

    for i := 0; i < len(temp); i++ {
        if i == index {
            // comma dot idiom = check if key in map
            value, ok := temp[i+1]

            // check that next index exists
            if ok && i <= len(temp) {
                newSlice[i] = value
                continue
            }
        }

        if i > index {
            newSlice[i] = temp[i+1]
            continue
        }

        newSlice[i] = temp[i]
    }

    return newSlice
}

I won’t go into concurrency and the like (Goroutines, channels…) here which are more advanced topics that make Go apart from other languages.

Keep learning new things, never stops !

Top Vue.js Developers in USA

Top Vue.js Developers in USA

Vue.js is an extensively popular JavaScript framework with which you can create powerful as well as interactive interfaces. Vue.js is the best framework when it comes to building a single web and mobile apps.

We, at HireFullStackDeveloperIndia, implement the right strategic approach to offer a wide variety through customized Vue.js development services to suit your requirements at most competitive prices.

Vue.js is an open-source JavaScript framework that is incredibly progressive and adoptive and majorly used to build a breathtaking user interface. Vue.js is efficient to create advanced web page applications.

Vue.js gets its strength from the flexible JavaScript library to build an enthralling user interface. As the core of Vue.js is concentrated which provides a variety of interactive components for the web and gives real-time implementation. It gives freedom to developers by giving fluidity and eases the integration process with existing projects and other libraries that enables to structure of a highly customizable application.

Vue.js is a scalable framework with a robust in-build stack that can extend itself to operate apps of any proportion. Moreover, vue.js is the best framework to seamlessly create astonishing single-page applications.

Our Vue.js developers have gained tremendous expertise by delivering services to clients worldwide over multiple industries in the area of front-end development. Our adept developers are experts in Vue development and can provide the best value-added user interfaces and web apps.

We assure our clients to have a prime user interface that reaches end-users and target the audience with the exceptional user experience across a variety of devices and platforms. Our expert team of developers serves your business to move ahead on the path of success, where your enterprise can have an advantage over others.

Here are some key benefits that you can avail when you decide to hire vue.js developers in USA from HireFullStackDeveloperIndia:

  • A team of Vue.js developers of your choice
  • 100% guaranteed client satisfaction
  • Integrity and Transparency
  • Free no-obligation quote
  • Portal development solutions
  • Interactive Dashboards over a wide array of devices
  • Vue.js music and video streaming apps
  • Flexible engagement model
  • A free project manager with your team
  • 24*7 communication with your preferred means

If you are looking to hire React Native developers in USA, then choosing HireFullStackDeveloperIndia would be the best as we offer some of the best talents when it comes to Vue.js.