← All EduBytes

Learning your second programming language is a different skill

31 August 2026 · 4 min read

Every guide to a new language is written for someone who has never programmed. If you already have ten years of it, that guide is not just slow — the help itself is what is slowing you down.

You have written Python for eight years. You need to learn Go. So you open the best-regarded introduction you can find and the first thing it does is explain that a function is a reusable block of code.

The obvious diagnosis is that you picked a beginner resource. Usually you didn’t. Almost every introduction to almost every language is written for someone who has never programmed, because that is the largest audience and because assuming nothing is the only assumption that is never insulting.

The less obvious diagnosis is that the help itself is now the obstacle.

Support that helps a novice hurts an expert

This has a name in the instructional design literature: the expertise reversal effect. Techniques that reliably improve learning for novices — worked examples, extra explanation, step-by-step scaffolding, careful restatement — become progressively less useful as knowledge grows, and past a point become actively harmful. Not merely redundant. Worse than nothing.

The mechanism is straightforward once stated. A novice has no mental structure for the material, so scaffolding gives them one. An expert already has one, so now they must process the explanation and reconcile it against the structure they already hold — is this the same idea I know under a different name, or is it subtly different, and if so where? That reconciliation is real work. The support has added load rather than removing it.

Which is why the beginner Go tutorial is not merely slow for you. It is genuinely harder to extract what you need from it than from a terser document, and the tiredness you feel reading it is not impatience.

The four things you actually need, none of which are in chapter one

When you already know a language, learning another one is not a smaller version of learning the first. It is a different task with a different shape:

1. The diff, not the whole. Perhaps ninety per cent of what you know transfers directly. Loops, functions, types, scope, data structures, the entire practice of decomposing a problem — that is not language knowledge, it is programming knowledge, and you have it. You need the ten per cent that differs, and you need it isolated.

2. Where your existing intuition is now wrong. This is the dangerous category, and it is the reason the diff is not enough on its own.

3. What a native actually writes. You can write Python in Go, and it will compile, and it will pass tests, and every Go programmer who reads it will know exactly where you came from. The gap between “correct” and “idiomatic” is invisible from inside your old language and it is most of what fluency means.

4. The conventions around the language. Project layout, how tests are organised, how dependencies are managed, how errors are expected to be handled, what the community argues about. None of this is in the language specification and all of it is required to work.

The false friends are what actually get you

Of those four, the second deserves its own section, because it is the one you cannot self-diagnose.

When you learn your first language, you know you know nothing. Everything is approached carefully. When you learn your fifth, you approach it with a set of strong, fast, mostly-correct intuitions — and the failures are precisely the places where an intuition is confident and wrong.

Coming from Python to Go, you carry a model of concurrency shaped by a global interpreter lock and by threads being something you mostly avoid. Go’s model is different in kind, not degree, and the habits that were prudent in one are limiting in the other. Coming from Python to Go you also carry a model of interfaces as things you explicitly inherit; Go satisfies them implicitly, and until someone tells you that directly, you will keep looking for the declaration.

Coming from Java to Python, you bring class hierarchies to problems that want a function and a dictionary. Coming from JavaScript to almost anything, you bring a set of assumptions about equality and asynchrony that are unusually local to JavaScript.

These are not errors of ignorance. They are errors of transfer, and the defining property of a transfer error is that it feels like knowledge. You will not search for the answer, because you do not have a question.

Which is why the document you want does not exist

Notice what the four needs above have in common: every one of them depends on which language you are coming from, not only on which you are going to.

“Rust for C++ programmers” and “Rust for Python programmers” are not the same document with different pacing. They are different documents. For the C++ programmer, the borrow checker is largely a formalisation of discipline they were already exercising by hand, and the interesting content is where the compiler disagrees with their instincts. For the Python programmer, the borrow checker is an alien concept and manual memory management is new and the type system is new. The first reader needs a diff. The second needs a foundation.

So a genuinely useful set of guides for one target language is not one document. It is one per plausible origin, times a couple of levels of depth — and then the same again for the next language. Nobody is going to write that grid, and the handful of “X for Y programmers” posts that do exist are mostly one enthusiast’s weekend, five years old, and stop before the idioms.

The gap is not that nobody thought of it. It is that writing one document per reader was never economically possible, so the whole industry standardised on the one document that assumes the least — and everybody with existing knowledge has been paying an expertise-reversal tax on every language they have learned since their first.