Section 15
JSON & HTTP
Python uses json and requests/flask/fastapi. Go has JSON and HTTP in the standard library — production-grade, no third-party packages needed. This is where Go's practical value becomes immediately obvious.
JSON
Python
import json
data = {"name": "Alice", "score": 95}
s = json.dumps(data)
parsed = json.loads(s)
Go
type User struct {
Name string `json:"name"`
Score int `json:"score"`
}
u := User{Name: "Alice", Score: 95}
b, _ := json.Marshal(u) // []byte
var parsed User
json.Unmarshal(b, &parsed) // fills struct
Struct tags (`json:"name"`) control serialization. omitempty skips zero values. - excludes a field entirely.
type Event struct {
ID string `json:"id"`
Timestamp int64 `json:"ts"`
Payload any `json:"payload,omitempty"` // skip if nil
Internal string `json:"-"` // never serialize
}
HTTP Server
package main
import (
"encoding/json"
"net/http"
)
func handleHealth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /health", handleHealth) // Go 1.22+ pattern
mux.HandleFunc("POST /api/events", handleCreate)
http.ListenAndServe(":8080", mux)
}
HTTP Client
func fetchUser(id string) (*User, error) {
resp, err := http.Get(fmt.Sprintf("https://api.example.com/users/%s", id))
if err != nil {
return nil, fmt.Errorf("fetching user: %w", err)
}
defer resp.Body.Close()
var u User
if err := json.NewDecoder(resp.Body).Decode(&u); err != nil {
return nil, fmt.Errorf("decoding: %w", err)
}
return &u, nil
}
defer Is Your Context Manager
Python uses with open() as f: to ensure cleanup. Go uses defer — it schedules a function call to run when the enclosing function returns. defer resp.Body.Close() is the Go equivalent of a context manager. Deferred calls execute in LIFO order.
Section 16
The Full Mapping Table
Reference sheet for translating Python concepts to Go.
| Python | Go | Key Difference |
|---|---|---|
x = 5 | x := 5 | Type inferred, immutable by convention |
None | nil | Only for pointers, slices, maps, channels, interfaces |
raise ValueError | return fmt.Errorf(...) | Errors are return values, not exceptions |
try/except | if err != nil {} | No exception unwinding |
list | []T (slice) | Typed, backed by arrays |
dict | map[K]V | Typed keys and values |
set | map[T]struct{} | No built-in set type |
tuple | Multiple return values / struct | No tuple type |
for x in items: | for _, x := range items {} | range yields index, value |
f"Hello {name}" | fmt.Sprintf("Hello %s", name) | Printf-style formatting |
print() | fmt.Println() | Package-level function |
class Foo: | type Foo struct{} | No classes, no __init__ |
| Inheritance | Embedding + interfaces | Composition over inheritance |
ABC / Protocol | interface | Implicit satisfaction — no implements |
lambda x: x+1 | func(x int) int { return x+1 } | No shorthand syntax |
@decorator | Higher-order functions / middleware | No decorator syntax |
with open() as f: | defer f.Close() | Deferred cleanup, LIFO order |
pip install | go get | Module-aware, checksum-verified |
pytest | go test | Built into the toolchain |
asyncio | Goroutines + channels | True parallelism, no GIL, no async/await |
multiprocessing | Goroutines (shared memory) | No process boundary — goroutines share heap |
| GIL | Doesn't exist | Goroutines run on real OS threads |
json.dumps/loads | json.Marshal/Unmarshal | Struct tags control field mapping |
flask/fastapi | net/http | Production HTTP server in stdlib |
*args | ...T (variadic) | Single typed variadic parameter |
**kwargs | Options struct / functional options | No keyword arguments |