Learning golang as a javascript developer
After a decade of working with JavaScript, primarily TypeScript, I’ve recently become interested in exploring new languages. In the past few months, Go (Golang) has particularly caught my attention. Today, I’ll be comparing these two languages from my perspective.
Facts
-
Performance: Go outperforms JavaScript in both memory usage and overall performance. However, with the introduction of the Bun.js runtime, JavaScript performance has become more comparable ( see [3], [4] ). Despite this, Go remains the stronger choice for performance-critical applications.
-
Both languages treat functions as first-class entities, allowing them to be passed as arguments, returned as values, nested within other functions, and to form closures.
-
Release year:
- Go was publicly announced in November 2009, and version 1.0 was released in March 2012
- JavaScript was invented by Brendan Eich in 1995. It was developed for Netscape 2, and became the ECMA-262 standard in 1997. The language saw a major evolution in 2015 with the release of ES6 (also known as ECMAScript 2015), which introduced significant features like ES modules, making JavaScript more powerful and versatile.
-
Number of keywords ( for, if, etc.)
- Go has 25 keywords
- JavaScript has 63 keywords
High level
Feature | Go | JavaScript |
---|---|---|
Type System | Statically typed | Dynamically typed |
Compilation | Compiles to machine code | Interpreted by browsers or by runtime like Node.js, Bun.js etc. |
Concurrency | Multi-threaded via goroutines | Event-driven, non-blocking, single-threaded via the event loop |
Speed | Generally faster due to compiled nature and lower-level access | Slower compared to Go, especially in CPU-intensive tasks |
Memory Management | Garbage collection (GC) | Garbage collection (GC) |
Ecosystem | Focused on backend services, cloud-native apps, and microservices | Massive ecosystem for frontend and backend (Node.js), supports web and mobile applications |
Error Handling | Explicit error handling via error return type | Exception handling with try/catch like in other languages |
Tooling | Built-in tools (e.g., go fmt , go build , go test ) | Tooling support via multiple third-party, like npm , tsc , eslint , prettier , webpack etc. |
Compilation Speed | Very fast compilation, designed for speed | Relatively fast but depends on the tooling |
Generics | Supported (since Go 1.18) | Supported |
Inheritance/Composition | No classical inheritance; uses composition | Supports classical inheritance (via class and extends ) |
Null/Undefined Safety | No concept of null , only nil for pointers and references | Has null , undefined , and optional chaining for safety |
Use Case | Backend services, microservices, high-performance apps, cloud-native systems | Web development, full-stack applications, mobile apps (via frameworks like React Native), server-side (Node.js) |
Deployment | Produces a single binary executable | Requires Node.js runtime or browsers for execution |
Learning Curve | Easier for those with experience | Easier for beginners, especially for web developers |
Syntax
Variables
-
Go: Strongly typed with explicit declaration or type inference using :=
// Explicit type var name string = "John" // Inferred type age := 30
-
Javascript: Variables are declared using let and const
let name = "John"; let age = 30;
Functions
-
Go functions explicitly define the parameter and return types. Named return values are also possible.
func greet(name string) string { return "Hello " + name } result := greet("John")
-
JavaScript functions can have optional and default parameters
function greet(name) { return `Hello ${name}`; } const result = greet("John");
Loops
-
Go only has a for loop, which can function like a traditional for, while, or range-based loop.
for i := 0; i < 5; i++ { fmt.Println(i) } // Range-based loop arr := []int{1, 2, 3} for _, value := range arr { fmt.Println(value) }
-
JavaScriptsupports for, for…of, for…in, while, and do…while loops
for (let i = 0; i < 5; i++) { console.log(i); } // For...of loop const arr = [1, 2, 3]; for (const value of arr) { console.log(value); }
Conditionals
-
Go uses if and switch statements, with strict type checks (no automatic type coercion).
age := 20 if age >= 18 { fmt.Println("Adult") } else { fmt.Println("Minor") } // Switch switch age { case 18: fmt.Println("Just an adult") case 30: fmt.Println("Mature adult") default: fmt.Println("Age unknown") }
-
JavaScript also supports if, else, and switch
let age = 20; if (age >= 18) { console.log("Adult"); } else { console.log("Minor"); } // Switch switch (age) { case 18: console.log("Just an adult"); break; case 30: console.log("Mature adult"); break; default: console.log("Age unknown"); }
Structs vs Classes
-
Go has struct for defining custom data types and doesn’t have classes or inheritance, but uses composition.
type Person struct { Name string Age int } person := Person{Name: "John", Age: 30} fmt.Println(person.Name)
-
JavaScript uses classes with classical inheritance
class Person { constructor(name, age) { this.name = name; this.age = age } greet() { return `Hello, my name is ${this.name}`; } } const person = new Person("John", 30); console.log(person.greet());
Interfaces
-
Go interfaces are satisfied implicitly (if a type implements the methods, it satisfies the interface).
type Speaker interface { Speak() string } type Person struct { Name string } func (p Person) Speak() string { return "Hello, my name is " + p.Name } var s Speaker = Person{Name: "John"} fmt.Println(s.Speak())
-
JavaScript interfaces define the structure of objects and can be implemented by classes.
interface Speaker { speak(): string; } class Person implements Speaker { constructor(name) { this.name = name } speak() { return `Hello, my name is ${this.name}`; } } const person: Speaker = new Person("John"); console.log(person.speak());
Error Handling
-
Go does not have exceptions. It uses explicit error handling through multiple return values.
func divide(a, b float64) (float64, error) { if b == 0 { return 0, fmt.Errorf("cannot divide by zero") } return a / b, nil } result, err := divide(4, 0) if err != nil { fmt.Println(err) }
-
JavaScript uses try/catch for exception handling.
function divide(a, b) { if (b === 0) { throw new Error("Cannot divide by zero"); } return a / b; } try { const result = divide(4, 0); } catch (err) { console.error(err.message); }
Concurrency
-
Go has built-in support for concurrency via goroutines and channels.
func sayHello() { fmt.Println("Hello") } go sayHello() // Runs concurrently
-
JavaScript uses asynchronous programming with async/await
async function sayHello() { console.log("Hello"); } sayHello(); // Runs asynchronously