DEV Community

OdaloV
OdaloV

Posted on

A Go Dev's First Month with JavaScript

I learned Go first. When I started picking up JavaScript, I assumed it would just be "different words for the same ideas" I already knew. A week in, I realized it's not just different words, it's a different way of thinking about code entirely. Here's what stood out most in that first week.

Declaring variables: := vs let/const

In Go, this is second nature by the time you've written a few programs:

count := 0
name := "Amina"
Enter fullscreen mode Exit fullscreen mode

JavaScript has its own version, but it looks nothing like it:

let count = 0;
const name = "Amina";
Enter fullscreen mode Exit fullscreen mode

My fingers kept typing := out of habit, which JavaScript just doesn't understand at all. And there's no single equivalent, JS gives you a choice between let (reassignable) and const (not reassignable), where Go's := doesn't make that distinction for you upfront.

Types are more of a suggestion than a rule

Go locks in a variable's type the moment you declare it:

value := "hello"
value = 42 // compile error
Enter fullscreen mode Exit fullscreen mode

JavaScript doesn't care:

let value = "hello";
value = 42; // totally fine
Enter fullscreen mode Exit fullscreen mode

This was the biggest adjustment for me, not because it's hard, but because nothing stops you. In Go, the compiler catches a mistake like this before the program even runs. In JavaScript, the same mistake might run just fine and only cause problems three functions later, somewhere completely unrelated to where the actual issue started.

undefined where Go would give you a zero value

Go never leaves a variable truly empty, every type has a default:

var name string  // ""
var count int    // 0
Enter fullscreen mode Exit fullscreen mode

JavaScript has an actual concept of "nothing was assigned":

let name;
console.log(name); // undefined
Enter fullscreen mode Exit fullscreen mode

At first this felt like less to worry about, no need to think about what a "default" looks like. Then I ran into null as well, which is different from undefined but similarly means "empty," and I realized JavaScript actually gives you two ways to represent nothing instead of Go's one predictable zero value. Keeping track of which parts of my code might produce undefined versus null versus an actual value took more mental effort than Go's zero values ever did.

Curly braces, but looser about it

if count > 0 {
    fmt.Println("positive")
}
Enter fullscreen mode Exit fullscreen mode
if (count > 0) {
  console.log("positive");
}
Enter fullscreen mode Exit fullscreen mode

JavaScript wants parentheses around the condition, Go doesn't. Small thing, but my hands kept leaving them out during that first week.

The bigger surprise: JavaScript will run code with unused variables, unused function parameters, and even unreachable code without complaint. Go refuses to compile if you've declared something you never use. I didn't realize how much I'd come to rely on that safety net until it wasn't there.

Functions: fewer rules, but also fewer guarantees

func add(a int, b int) int {
    return a + b
}
Enter fullscreen mode Exit fullscreen mode
function add(a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

No types to declare on the parameters, which felt freeing at first. It stopped feeling that way the first time I called add("2", 3) and got "23" back instead of an error. JavaScript will coerce values instead of stopping you, where Go would've refused to compile the mismatch entirely.

Go's multiple return values also don't carry over. In Go, error handling is built into how a function returns:

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("cannot divide by zero")
    }
    return a / b, nil
}
Enter fullscreen mode Exit fullscreen mode

JavaScript reaches for try/catch instead, or a rejected Promise for anything asynchronous:

function divide(a, b) {
  if (b === 0) {
    throw new Error("cannot divide by zero");
  }
  return a / b;
}

try {
  const result = divide(10, 0);
} catch (err) {
  console.log("Error:", err.message);
}
Enter fullscreen mode Exit fullscreen mode

Neither approach is wrong, but switching from checking err != nil after every call to wrapping things in try/catch blocks was a genuine shift in how I thought about where failures could happen.

Semicolons, now optional-ish

Go doesn't want you to type semicolons at all, the compiler inserts them for you. JavaScript technically has automatic semicolon insertion too, but most style guides still expect you to type them yourself:

const name = "Amina";
let count = 0;
Enter fullscreen mode Exit fullscreen mode

Leaving them off doesn't break anything most of the time, but it's inconsistent enough that I just kept typing them to be safe.

What I'm taking into week two

  • The freedom of not declaring types is genuinely convenient for quick scripts, and genuinely risky for anything larger, since nothing catches a type mistake until it actually runs.
  • undefined and null both existing means I have to think about which one my code might actually produce, something Go's single zero-value concept never required.
  • try/catch is a different mental model from Go's explicit error returns, not just a different keyword for the same idea.
  • Async in JavaScript, async/await and Promises, doesn't map onto goroutines and channels at all. That one's going to take longer than a week to feel natural.

Coming from Go, JavaScript's flexibility felt like a relief at first and a little unsettling once I saw how much it lets slide. The syntax differences were the easy part to notice. The harder part was unlearning the assumption that the language would stop me before I made a mistake.

Top comments (0)