Golang / GoLang Production Patterns and Web Standards Interview Questions
What are the common API versioning strategies in Go HTTP services?
API versioning allows a service to evolve without breaking existing clients. Go supports several approaches, each with different trade-offs in URL clarity, header complexity, and routing ease.
// Strategy 1: URL path versioning (most common, most explicit) mux.HandleFunc("GET /v1/users/{id}", v1GetUser) mux.HandleFunc("GET /v2/users/{id}", v2GetUser) // new format, new endpoint // Sub-router pattern for clean version grouping func v1Routes() http.Handler { mux := http.NewServeMux() mux.HandleFunc("GET /users/{id}", v1GetUser) mux.HandleFunc("POST /users", v1CreateUser) return mux } func v2Routes() http.Handler { mux := http.NewServeMux() mux.HandleFunc("GET /users/{id}", v2GetUser) mux.HandleFunc("POST /users", v2CreateUser) return mux } mainMux := http.NewServeMux() mainMux.Handle("/v1/", http.StripPrefix("/v1", v1Routes())) mainMux.Handle("/v2/", http.StripPrefix("/v2", v2Routes())) // Strategy 2: Accept header versioning (content negotiation) // Accept: application/vnd.myapi.v2+json func versionedHandler(w http.ResponseWriter, r *http.Request) { accept := r.Header.Get("Accept") switch { case strings.Contains(accept, "vnd.myapi.v2"): v2GetUser(w, r) default: v1GetUser(w, r) } } // Strategy 3: Query parameter (least preferred) // GET /users/1?version=2 // Backward compatibility within a version: // - Add new optional fields (never remove) // - Use omitempty on optional response fields // - Return 422 for unrecognised required fields // - Treat unknown JSON keys in requests as valid (ignore, don't error)
More Related questions...