If you're coming from a TypeScript/JavaScript background and diving into Go, it can be helpful to draw parallels between the two languages to speed up your learning. While they are fundamentally different in many ways (Go being a statically-typed, compiled language, and TypeScript/JavaScript being dynamically typed, interpreted or transpiled languages), there are some useful analogies that will help make Go more intuitive.
1. Structs in Go ≈ Types in TypeScript
In TypeScript, you define types and interfaces to describe the shape of objects. Similarly, Go has structs
, which are used to define custom types. A struct can contain fields of different types, similar to how a TypeScript type or interface may contain different properties.
TypeScript:
type Book = {
title: string;
pages: number;
read(): void;
}
Go:
type Book struct {
Title string
Pages int
}
func (b Book) Read() {
fmt.Println("Reading", b.Title)
}
In both cases, you are defining the structure of an object. However, Go’s structs are more rigid and do not support inheritance, unlike TypeScript, which allows for more dynamic behavior with interfaces and class inheritance.
2. Methods in Go: Receivers ≈ Prototypes in JavaScript
In JavaScript, when you define a method on an object’s prototype, it’s associated with instances of that object. Go uses a similar concept with receiver functions that are tied to a specific struct. This feels similar to how functions are attached to objects in JavaScript via prototypes.
JavaScript:
function Book(title, pages) {
this.title = title;
this.pages = pages;
}
Book.prototype.read = function() {
console.log("Reading", this.title);
}
Go:
type Book struct {
Title string
Pages int
}
func (b Book) Read() {
fmt.Println("Reading", b.Title)
}
In Go, the Read
method has a receiver (b Book)
, which acts similarly to how methods are associated with prototypes in JavaScript. It gives you the object’s instance (b
here), letting you access the fields and use the method.
3. let
, var
, const
in TypeScript ≈ Variable Declaration in Go
The way you declare variables in Go is reminiscent of JavaScript’s let
, var
, and const
. In Go, variables are declared with var
, and constants with const
, much like TypeScript.
TypeScript:
let name: string = "TypeScript";
const maxItems: number = 100;
Go:
var name string = "Go"
const maxItems int = 100
The :=
shorthand in Go feels somewhat like JavaScript’s let
in that it allows for quick variable declaration:
name := "Go" // type inference, like in TypeScript
In Go, there is no distinction between let and const like in JavaScript. By default, all variables in Go are mutable when declared with var, meaning their values can be changed later. If you want to make a variable immutable in Go, you must explicitly use the const keyword. Unlike JavaScript, where you have both let for mutable variables and const for immutable ones, in Go, everything is mutable unless you declare it as const.
4. Go Interfaces ≈ TypeScript Interfaces (with differences)
TypeScript interfaces define the shape of objects, while Go interfaces define behavior (i.e., a set of methods an object must have). In Go, an object "implements" an interface implicitly by having all required methods, which contrasts with TypeScript's explicit implementation.
TypeScript:
interface Reader {
read(): void;
}
class Book implements Reader {
read() {
console.log("Reading a book");
}
}
Go:
type Reader interface {
Read()
}
type Book struct {
Title string
}
func (b Book) Read() {
fmt.Println("Reading", b.Title)
}
In Go, any type that implements the Read
method is considered to implement the Reader
interface, even without explicitly declaring it.
5. Error Handling in Go ≈ Try-Catch in JavaScript (but different)
Error handling in Go feels very different compared to JavaScript’s try-catch
. In Go, error handling is done explicitly with return values, while JavaScript uses exceptions.
JavaScript:
try {
// Some code
} catch (error) {
console.error(error);
}
Go:
file, err := os.Open("file.txt")
if err != nil {
log.Fatal(err)
}
In Go, errors are returned from functions and need to be checked explicitly, which leads to more predictable control flow but requires more manual error handling compared to JavaScript’s try-catch
mechanism.
6. Package System in Go ≈ ES Modules in TypeScript
In TypeScript, you organize your code into modules that can import/export other pieces of functionality. Go has a similar package system where each file is part of a package, and packages can import functionality from other packages.
TypeScript:
// module1.ts
export const greet = () => console.log("Hello");
// module2.ts
import { greet } from "./module1";
greet();
Go:
// main.go
package main
import "fmt"
func main() {
fmt.Println("Hello, Go")
}
In Go, package main
is the entry point of your application, similar to how a main file might serve as an entry point for a TypeScript project using ES modules.
7. Concurrency in Go: Goroutines ≈ Asynchronous Programming
JavaScript's asynchronous programming with async
/await
and promises feels somewhat analogous to Go’s goroutines. Goroutines allow functions to run concurrently, making Go’s concurrency model very powerful.
JavaScript:
async function fetchData() {
const data = await fetch(url);
console.log(data);
}
Go:
func fetchData() {
fmt.Println("Fetching data...")
}
go fetchData() // Runs concurrently
With Go's goroutines, you can launch functions concurrently with the go
keyword, while TypeScript achieves this through async
/await
and promises.
Conclusion
Switching from TypeScript/JavaScript to Go might seem daunting at first, but drawing these comparisons can help make the transition smoother. Understanding Go's stricter type system, explicit interfaces, and concurrency model will make your journey rewarding. Once you get the hang of Go’s more explicit and structured nature, you’ll appreciate its performance and reliability in building robust systems.
Top comments (3)
Cool blog.
Very helpful
Thanks for sharing this