Ir al contenido

Go for JavaScript Developers

A practical guide to understanding Go through familiar JavaScript patterns and concepts.

Variables & Constants

Variable Declaration

JavaScript:

let name = "John";
var age = 25;
const count = 10;

Go:

var name string = "John"
var age int = 25
const count int = 10

// Short declaration (only inside functions)
name := "John"
age := 25

Multiple Variables

JavaScript:

let x = 1, y = 2, z = 3;
const {name, age} = user;

Go:

var x, y, z int = 1, 2, 3

// Named return values
func getUser() (name string, age int) {
    return "John", 25
}

Data Types

ConceptJavaScriptGo
Stringstringstring
Numbernumberint, int32, int64, float32, float64
Booleanbooleanbool
Arrayarrayslice or array
Objectobjectstruct
Functionfunctionfunc
Any Typeanyinterface{}

Structs vs Objects

JavaScript:

const user = {
    name: "John",
    age: 25,
    email: "john@example.com"
};

user.name; // "John"

Go:

type User struct {
    Name  string
    Age   int
    Email string
}

user := User{Name: "John", Age: 25, Email: "john@example.com"}
user.Name // "John"

Functions

Basic Functions

JavaScript:

function add(a, b) {
    return a + b;
}

// Arrow function
const multiply = (a, b) => a * b;

Go:

func add(a int, b int) int {
    return a + b
}

// Multiple return values
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

Function as First-Class Object

JavaScript:

const map = (arr, fn) => arr.map(fn);
const square = x => x * x;
map([1, 2, 3], square); // [1, 4, 9]

Go:

func map_(arr []int, fn func(int) int) []int {
    result := make([]int, len(arr))
    for i, v := range arr {
        result[i] = fn(v)
    }
    return result
}

square := func(x int) int { return x * x }
map_([]int{1, 2, 3}, square) // [1, 4, 9]

Arrays & Slices

Collections

JavaScript:

let arr = [1, 2, 3];
arr.push(4);
arr.map(x => x * 2);
arr.filter(x => x > 2);
arr.length;

Go:

// Arrays (fixed size)
var arr [3]int = [3]int{1, 2, 3}

// Slices (dynamic)
slice := []int{1, 2, 3}
slice = append(slice, 4)
len(slice) // 4

// Iteration
for i, v := range slice {
    fmt.Println(i, v)
}

Loops

For Loops

JavaScript:

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

// forEach
[1, 2, 3].forEach(num => {
    console.log(num);
});

// for...of
for (const item of array) {
    console.log(item);
}

Go:

// Traditional for loop
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

// While loop
i := 0
for i < 10 {
    fmt.Println(i)
    i++
}

// Range loop (like for...of)
for _, item := range array {
    fmt.Println(item)
}

// Break and continue
for i := 0; i < 10; i++ {
    if i == 5 {
        break
    }
    if i == 2 {
        continue
    }
}

Conditionals

if/else

JavaScript:

if (age >= 18) {
    console.log("Adult");
} else if (age >= 13) {
    console.log("Teen");
} else {
    console.log("Child");
}

// Ternary
const status = age >= 18 ? "Adult" : "Child";

Go:

if age >= 18 {
    fmt.Println("Adult")
} else if age >= 13 {
    fmt.Println("Teen")
} else {
    fmt.Println("Child")
}

// Short if
if err := doSomething(); err != nil {
    log.Fatal(err)
}

Switch Statements

JavaScript:

switch (day) {
    case "Monday":
        console.log("Start of week");
        break;
    case "Friday":
        console.log("End of week");
        break;
    default:
        console.log("Midweek");
}

Go:

switch day {
case "Monday":
    fmt.Println("Start of week")
case "Friday":
    fmt.Println("End of week")
default:
    fmt.Println("Midweek")
}

// Switch without expression
switch {
case age < 13:
    fmt.Println("Child")
case age < 18:
    fmt.Println("Teen")
default:
    fmt.Println("Adult")
}

Error Handling

Exceptions vs Error Returns

JavaScript:

try {
    riskyOperation();
} catch (error) {
    console.error("Error:", error.message);
} finally {
    cleanup();
}

function riskyOperation() {
    throw new Error("Something went wrong");
}

Go:

// Go uses explicit error returns (no exceptions)
result, err := riskyOperation()
if err != nil {
    log.Fatal("Error:", err)
}

func riskyOperation() (string, error) {
    return "", errors.New("Something went wrong")
}

// Custom errors
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

Maps (Objects/Dictionaries)

Key-Value Pairs

JavaScript:

const user = {
    name: "John",
    age: 25,
    city: "NYC"
};

user.name; // "John"
user["age"]; // 25
delete user.city;

Go:

user := map[string]interface{}{
    "name": "John",
    "age":  25,
    "city": "NYC",
}

user["name"]        // "John"
value, ok := user["age"] // Check if key exists
delete(user, "city")

// Typed maps
scores := map[string]int{
    "Alice": 95,
    "Bob":   87,
}

Pointers

Memory References

JavaScript:

// JavaScript handles references automatically
let obj = {name: "John"};
let ref = obj;
ref.name = "Jane"; // Changes obj too

// Primitives are copied
let x = 5;
let y = x;
y = 10; // x is still 5

Go:

// Pointers are explicit
type User struct {
    Name string
}

user := User{Name: "John"}
ptr := &user          // Get pointer to user
ptr.Name = "Jane"     // Changes user.Name
*ptr                  // Dereference pointer

// Function with pointer receiver (mutates original)
func (u *User) setName(name string) {
    u.Name = name
}

// Function with value receiver (doesn't mutate)
func (u User) getName() string {
    return u.Name
}

Interfaces

Type-based Polymorphism

JavaScript:

class Animal {
    speak() {
        throw new Error("speak() must be implemented");
    }
}

class Dog extends Animal {
    speak() {
        return "Woof";
    }
}

class Cat extends Animal {
    speak() {
        return "Meow";
    }
}

Go:

// Interface definition
type Animal interface {
    Speak() string
}

type Dog struct {
    Name string
}

func (d Dog) Speak() string {
    return "Woof"
}

type Cat struct {
    Name string
}

func (c Cat) Speak() string {
    return "Meow"
}

// Any type implementing Animal interface
func makeSound(a Animal) {
    fmt.Println(a.Speak())
}

Goroutines vs Promises

Concurrency

JavaScript:

// Promises
Promise.all([
    fetch('url1'),
    fetch('url2')
]).then(results => {
    console.log(results);
});

// Async/await
async function fetchData() {
    try {
        const result1 = await fetch('url1');
        const result2 = await fetch('url2');
        console.log(result1, result2);
    } catch (error) {
        console.error(error);
    }
}

Go:

// Goroutines with channels
results := make(chan string, 2)

go func() {
    results <- fetchData("url1")
}()

go func() {
    results <- fetchData("url2")
}()

result1 := <-results
result2 := <-results

// WaitGroup for synchronization
var wg sync.WaitGroup
wg.Add(2)

go func() {
    defer wg.Done()
    // do work
}()

go func() {
    defer wg.Done()
    // do work
}()

wg.Wait()

Package Management

Imports

JavaScript:

import { add, subtract } from './math.js';
import React from 'react';
import * as utils from './utils.js';

Go:

import (
    "fmt"
    "errors"
    "github.com/username/package"
)

// Using imported packages
fmt.Println("Hello")
err := errors.New("Error")

Methods vs Functions

Receivers

JavaScript:

class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }

    area() {
        return this.width * this.height;
    }
}

const rect = new Rectangle(10, 20);
rect.area(); // 200

Go:

type Rectangle struct {
    Width, Height float64
}

// Method (has receiver)
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Function (no receiver)
func CalculateArea(width, height float64) float64 {
    return width * height
}

rect := Rectangle{Width: 10, Height: 20}
rect.Area() // 200

Defer & Cleanup

Resource Cleanup

JavaScript:

try {
    const file = openFile('data.txt');
    const content = file.read();
    console.log(content);
} finally {
    file.close();
}

Go:

file, err := os.Open("data.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close() // Executes when function returns

content, _ := io.ReadAll(file)
fmt.Println(string(content))
// file.Close() is called automatically

Testing

Test Structure

JavaScript (Jest):

describe('Math operations', () => {
    test('adds two numbers', () => {
        expect(add(2, 3)).toBe(5);
    });
});

Go:

// Filename: math_test.go
package mypackage

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf("Expected 5, got %d", result)
    }
}

// Run with: go test ./...

Key Differences Summary

AspectJavaScriptGo
Type SystemDynamicStatic, strongly typed
Null Handlingnull/undefinednil (explicit)
Error HandlingExceptions (try/catch)Error returns
ConcurrencyPromises/async-awaitGoroutines/channels
CompilationInterpreted/JITCompiled
Memory ManagementGarbage collectedGarbage collected
PointersImplicitExplicit
InheritancePrototype-basedComposition-based
Package Managernpm/yarngo modules

Resources


Last updated: 2026-03-30