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"
JavaScript has its own version, but it looks nothing like it:
let count = 0;
const name = "Amina";
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
JavaScript doesn't care:
let value = "hello";
value = 42; // totally fine
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
JavaScript has an actual concept of "nothing was assigned":
let name;
console.log(name); // undefined
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")
}
if (count > 0) {
console.log("positive");
}
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
}
function add(a, b) {
return a + b;
}
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
}
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);
}
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;
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.
-
undefinedandnullboth existing means I have to think about which one my code might actually produce, something Go's single zero-value concept never required. -
try/catchis a different mental model from Go's explicit error returns, not just a different keyword for the same idea. - Async in JavaScript,
async/awaitand 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)