HTTP Server: Go vs Rust
Let’s compare how a basic HTTP server looks in Go and Rust — two languages often mentioned together when performance and reliability matter.
A Minimal HTTP Server
Goal: listen on port 8080, respond with Hello, World! for any GET request to /.
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
use std::io::{BufRead, BufReader, Write};
use std::net::{TcpListener, TcpStream};
fn handle(mut stream: TcpStream) {
let reader = BufReader::new(&stream);
for line in reader.lines() {
if line.unwrap_or_default().is_empty() { break; }
}
let response = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello, World!";
stream.write_all(response.as_bytes()).unwrap();
}
fn main() {
let listener = TcpListener::bind("0.0.0.0:8080").unwrap();
for stream in listener.incoming().flatten() {
handle(stream);
}
}
Go’s stdlib ships a full HTTP server with routing. In Rust, the standard library only gives you TCP — in production you’d use Axum or Actix Web.
Routing and JSON
Add a /ping route that returns JSON.
package main
import (
"encoding/json"
"net/http"
)
type Pong struct {
Status string `json:"status"`
}
func pingHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(Pong{Status: "ok"})
}
func main() {
http.HandleFunc("/ping", pingHandler)
http.ListenAndServe(":8080", nil)
}
use axum::{routing::get, Router};
use serde::Serialize;
use axum::Json;
#[derive(Serialize)]
struct Pong {
status: &'static str,
}
async fn ping() -> Json<Pong> {
Json(Pong { status: "ok" })
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/ping", get(ping));
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Which to Pick?
| Go | Rust | |
|---|---|---|
| Learning curve | Low | High |
| Built-in HTTP lib | Yes | TCP only |
| Async model | Goroutines | Tokio/async-std |
| Compile speed | Fast | Slow |
| Runtime overhead | GC | None |
Go is the pragmatic choice for most backend services. Rust gives you maximum control when every millisecond and every byte counts.