Go (Golang)
Go (often called Golang) is a statically typed, compiled programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. Released in 2009, Go was created to address shortcomings in other languages used at Google for building large-scale, high-performance systems. For JavaScript and TypeScript developers, Go offers a compelling option for backend services with a focus on simplicity and performance.
What is Go?
Go is designed for simplicity, reliability, and efficiency. It combines:
- Fast compilation like dynamic languages
- Execution speed like C/C++
- Easy concurrency with goroutines
- Simple syntax with minimal features
- Built-in tooling for formatting, testing, and dependencies
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Go for JavaScript/TypeScript Developers
What You'll Recognize
If you know JavaScript/TypeScript, some concepts will feel familiar:
- Functions as first-class citizens
- Closures and anonymous functions
- Garbage collection (no manual memory management)
- JSON handling is straightforward
- Package-based modules
// Functions as values (like JavaScript)
add := func(a, b int) int {
return a + b
}
result := add(5, 3) // 8
What's Different
Statically Typed (Compile-time)
Unlike JavaScript, Go is statically typed:
var name string = "Alice"
var age int = 25
// Type inference (like TypeScript's let)
name := "Alice" // Compiler infers 'string'
age := 25 // Compiler infers 'int'
No Classes, Use Structs
Go doesn't have classes. Instead, it uses structs with methods:
type User struct {
Name string
Email string
}
func (u User) Greet() string {
return "Hello, " + u.Name
}
user := User{Name: "Alice", Email: "[email protected]"}
fmt.Println(user.Greet()) // Hello, Alice
Error Handling: No Try/Catch
Go uses explicit error returns instead of exceptions:
// JavaScript/TypeScript
try {
const data = await fetchUser(id);
} catch (error) {
console.error(error);
}
// Go
data, err := fetchUser(id)
if err != nil {
log.Printf("Error: %v", err)
return
}
// Use data...
Pointers (But Simple)
Go has pointers, but they're simpler than C/C++:
func updateName(u *User, newName string) {
u.Name = newName // Automatically dereferenced
}
user := User{Name: "Alice"}
updateName(&user, "Bob") // Pass pointer with &
fmt.Println(user.Name) // Bob
Why Go?
1. Speed
Go compiles to native machine code and is significantly faster than Node.js:
- Compilation: Seconds for large projects
- Execution: 10-100x faster than JavaScript for CPU-intensive tasks
- Startup time: Instant (no runtime to load)
// Processing millions of records
for _, record := range records { // Much faster than JS for loops
processRecord(record)
}
2. Concurrency
Go's killer feature is goroutines - lightweight threads that make concurrent programming easy:
// Start concurrent operations (like async/await but easier)
go fetchUser(id1) // Runs concurrently
go fetchUser(id2) // Runs concurrently
go fetchUser(id3) // Runs concurrently
// With channels for communication
results := make(chan User)
go func() {
user, _ := fetchUser(id)
results <- user // Send to channel
}()
user := <-results // Receive from channel
Comparison to JavaScript:
// JavaScript - async/await
const [user1, user2, user3] = await Promise.all([
fetchUser(id1),
fetchUser(id2),
fetchUser(id3),
]);
// Go - goroutines
ch := make(chan User, 3)
for _, id := range []int{id1, id2, id3} {
go func(id int) {
user, _ := fetchUser(id)
ch <- user
}(id)
}
users := []User{<-ch, <-ch, <-ch}
Goroutines are cheaper than JavaScript Promises for thousands of concurrent operations.
3. Simple Deployment
Go compiles to a single binary with no dependencies:
# Build
go build -o myapp
# Deploy (just copy the binary)
./myapp
No need for:
node_modules/
(no dependencies to ship)- Runtime installation (Node.js)
- Version managers (nvm)
This makes Docker images tiny and deployment simple.
4. Built-in Tooling
Go comes with excellent tools out of the box:
go fmt # Format code (like Prettier, but standard)
go test # Run tests (built-in testing)
go mod init # Initialize module (like npm init)
go mod tidy # Clean up dependencies
go build # Compile binary
go run # Compile and run
5. Standard Library
Go's standard library is comprehensive. You can build HTTP servers without external dependencies:
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Compare to Express.js:
const express = require('express'); // External dependency
const app = express();
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(8080);
Where Go Excels
Backend Services & APIs
Go is popular for building REST APIs and microservices:
// Using Gin (like Express for Go)
package main
import "github.com/gin-gonic/gin"
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
r := gin.Default()
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
user := User{ID: 1, Name: "Alice", Email: "[email protected]"}
c.JSON(200, user)
})
r.Run(":8080")
}
DevOps Tools & CLI
Many popular tools are written in Go:
- Docker: Container platform
- Kubernetes: Container orchestration
- Terraform: Infrastructure as code
- GitHub CLI:
gh
command - Hugo: Static site generator
Go is excellent for CLI tools because of single binary distribution.
Cloud Services
Major cloud providers use Go extensively:
- Google: Internal services, Cloud Platform
- Uber: Microservices platform
- Dropbox: Performance-critical services
- Cloudflare: Edge services
- Twitch: Chat servers (handles millions of connections)
Real-time Systems
Go excels at handling many concurrent connections:
// WebSocket server handling thousands of connections
func handleWebSocket(conn *websocket.Conn) {
for {
var msg Message
err := conn.ReadJSON(&msg)
if err != nil {
break
}
// Process message
broadcastToAll(msg)
}
}
Go vs JavaScript/TypeScript
Aspect | JavaScript/Node.js | TypeScript | Go |
---|---|---|---|
Type System | Dynamic | Static (compile-time) | Static (compile-time) |
Performance | Slow | Slow (same as JS) | Fast (compiled) |
Concurrency | Event loop, async/await | Same as JS | Goroutines, channels |
Compilation | None (interpreted) | To JavaScript | To native binary |
Binary Size | N/A (needs runtime) | N/A | ~5-10 MB |
Startup Time | Slow | Slow | Instant |
Memory | High | High | Lower |
Learning Curve | Easy | Moderate | Moderate |
Ecosystem | Huge | Huge | Large (growing) |
Frontend | Yes (browsers) | Yes | No |
Backend | Yes (Node.js) | Yes | Yes (native) |
Common Use Cases for JS vs Go
Use Node.js/TypeScript when:
- Building full-stack apps (same language frontend/backend)
- Rapid prototyping
- Working with JSON/APIs heavily
- Team already knows JavaScript
- Using server-side rendering (React, Next.js)
- Real-time apps (Socket.io)
Use Go when:
- Performance is critical
- Building microservices
- Handling high concurrency (thousands of connections)
- Creating CLI tools
- Working with systems programming
- Need efficient resource usage (cloud costs)
- Simple deployment requirements
Learning Go from JavaScript
Syntax Comparison
Variables
// JavaScript
const name = "Alice";
let age = 25;
// Go
const name = "Alice" // or: name := "Alice"
var age = 25 // or: age := 25
Functions
// JavaScript
function add(a, b) {
return a + b;
}
// Go
func add(a int, b int) int {
return a + b
}
Arrays/Slices
// JavaScript
const numbers = [1, 2, 3, 4, 5];
numbers.push(6);
const doubled = numbers.map(n => n * 2);
// Go
numbers := []int{1, 2, 3, 4, 5}
numbers = append(numbers, 6)
var doubled []int
for _, n := range numbers {
doubled = append(doubled, n*2)
}
Objects/Structs
// JavaScript
const user = {
name: "Alice",
email: "[email protected]"
};
// Go
type User struct {
Name string
Email string
}
user := User{
Name: "Alice",
Email: "[email protected]",
}
Loops
// JavaScript
for (let i = 0; i < 10; i++) {
console.log(i);
}
// Go
for i := 0; i < 10; i++ {
fmt.Println(i)
}
Async/Concurrency
// JavaScript
async function fetchData() {
const result = await fetch(url);
const data = await result.json();
return data;
}
// Go
func fetchData() (Data, error) {
resp, err := http.Get(url)
if err != nil {
return Data{}, err
}
defer resp.Body.Close()
var data Data
err = json.NewDecoder(resp.Body).Decode(&data)
return data, err
}
Go Frameworks & Libraries
Web Frameworks
- Gin: Fast, Express-like framework
- Echo: High performance, minimalist
- Fiber: Inspired by Express.js
- Chi: Lightweight router
ORMs & Databases
- GORM: Full-featured ORM (like TypeORM)
- sqlx: Extensions for database/sql
- pgx: PostgreSQL driver and toolkit
Testing
- Built-in
testing
package - Testify: Assertions and mocks
- GoMock: Mocking framework
Utilities
- Viper: Configuration management
- Cobra: CLI applications
- Zap/Logrus: Structured logging
Gotchas for JS Developers
1. Error Handling
You'll write if err != nil
a lot:
data, err := fetchUser(id)
if err != nil {
return nil, err // Handle error
}
// Use data...
2. No undefined
or null
(mostly)
Go has zero values instead:
var name string // "" (empty string)
var age int // 0
var isActive bool // false
var ptr *User // nil (for pointers)
3. Exported vs Unexported
Capitalization matters:
type User struct {
Name string // Exported (public)
email string // Unexported (private)
}
4. No Inheritance
Go uses composition over inheritance:
type Writer struct {
Name string
}
type Blogger struct {
Writer // Embedded struct (composition)
Blog string
}
b := Blogger{
Writer: Writer{Name: "Alice"},
Blog: "myblog.com",
}
fmt.Println(b.Name) // Can access embedded fields
5. Multiple Return Values
Functions can return multiple values (commonly value + error):
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
result, err := divide(10, 2)
if err != nil {
log.Fatal(err)
}
fmt.Println(result) // 5
When to Learn Go
Learn Go if:
- You want to build high-performance backend services
- You're interested in DevOps/cloud infrastructure
- You want to understand systems programming
- You need better performance than Node.js
- You're building CLI tools or microservices
Stick with TypeScript if:
- You're primarily a frontend developer
- You need full-stack with same language
- Your team is JavaScript-focused
- You're building React applications
- Rapid iteration is more important than performance
Learning Resources
- A Tour of Go: go.dev/tour - Interactive browser-based tutorial
- Go by Example: gobyexample.com - Annotated example programs
- Effective Go: Official guide to idiomatic Go
- Learn Go with Tests: TDD approach to learning Go
- Go Web Examples: gowebexamples.com - Web development patterns
Real-World Examples
REST API Example
package main
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
)
type Article struct {
ID string `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
}
var articles []Article
func getArticles(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(articles)
}
func getArticle(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
for _, article := range articles {
if article.ID == params["id"] {
json.NewEncoder(w).Encode(article)
return
}
}
http.NotFound(w, r)
}
func main() {
router := mux.NewRouter()
router.HandleFunc("/articles", getArticles).Methods("GET")
router.HandleFunc("/articles/{id}", getArticle).Methods("GET")
http.ListenAndServe(":8000", router)
}
Concurrent Worker Pool
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, j)
time.Sleep(time.Second)
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Start 3 workers
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Send jobs
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= 9; a++ {
<-results
}
}
Key Takeaways
- Go is simple, fast, and great for backend services
- Excellent built-in concurrency with goroutines
- Compiles to single binary (easy deployment)
- Different from JavaScript but not hard to learn
- Great standard library, less need for external packages
- Used by major companies for performance-critical services
- Perfect for microservices, CLI tools, and cloud services
Related Topics
- TypeScript - Type-safe JavaScript alternative
- Rust - Systems programming with memory safety
- React - Go can serve as a backend for React apps
- JavaScript Frameworks - Frontend frameworks that pair with Go backends
For JavaScript/TypeScript developers, Go is an excellent second language that opens doors to backend development, DevOps, and systems programming. The learning curve is moderate, and the performance gains and simple deployment make it worth the investment.