Go API: REST, GraphQL and gRPC — What to Choose in 2025

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why Go is the Ideal Language for APIs?

\n\n

When it comes to building high-load APIs, Go (Golang) confidently ranks among the top. Its compiled nature, built-in concurrency support via goroutines, and minimalist syntax allow you to write fast and reliable microservices. But which protocol should you choose for your next project: classic REST, flexible GraphQL, or ultra-fast gRPC?

\n\n

In this article, we won't just list the differences — we'll write real Go code for each approach, analyze benchmarks, and provide clear selection criteria. Let's go!

\n\n

REST API in Go: A Proven Classic

\n\n

REST (Representational State Transfer) remains the de facto standard for public APIs. Go offers an excellent standard library net/http, as well as popular frameworks like gin and echo.

\n\n

Example of a REST Server in Pure Go

\n\n

Let's start with a simple CRUD service for managing tasks. Here's what a minimal REST API in Go looks like without third-party dependencies:

\n\n
package main\n\nimport (\n    "encoding/json"\n    "log"\n    "net/http"\n    "sync"\n)\n\ntype Task struct {\n    ID   int    `json:"id"`\n    Name string `json:"name"`\n}\n\nvar (\n    tasks   = []Task{{ID: 1, Name: "Learn Go"}}\n    mu      sync.Mutex\n    nextID  = 2\n)\n\nfunc getTasks(w http.ResponseWriter, r *http.Request) {\n    mu.Lock()\n    defer mu.Unlock()\n    w.Header().Set("Content-Type", "application/json")\n    json.NewEncoder(w).Encode(tasks)\n}\n\nfunc createTask(w http.ResponseWriter, r *http.Request) {\n    var task Task\n    if err := json.NewDecoder(r.Body).Decode(&task); err != nil {\n        http.Error(w, err.Error(), http.StatusBadRequest)\n        return\n    }\n    mu.Lock()\n    task.ID = nextID\n    nextID++\n    tasks = append(tasks, task)\n    mu.Unlock()\n    w.WriteHeader(http.StatusCreated)\n    json.NewEncoder(w).Encode(task)\n}\n\nfunc main() {\n    http.HandleFunc("/tasks", func(w http.ResponseWriter, r *http.Request) {\n        switch r.Method {\n        case http.MethodGet:\n            getTasks(w, r)\n        case http.MethodPost:\n            createTask(w, r)\n        default:\n            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)\n        }\n    })\n    log.Println("REST API started on :8080")\n    log.Fatal(http.ListenAndServe(":8080", nil))\n}\n
\n\n

Pros of REST in Go:

\n
    \n
  • Simplicity and predictability — each endpoint returns a fixed data structure
  • \n
  • Excellent caching via HTTP headers
  • \n
  • Wide tool support (Swagger, Postman)
  • \n
\n\n

Cons: Over-fetching and under-fetching of data. If the client only needs the task name, it still receives the full JSON.

\n\n

GraphQL in Go: Query Flexibility

\n\n

GraphQL solves the problem of data redundancy. The client decides which fields it needs. The Go community offers the powerful gqlgen library, which generates code from a schema.

\n\n

Example of a GraphQL Server with gqlgen

\n\n

First, let's define the schema.graphql schema:

\n\n
type Task {\n    id: ID!\n    name: String!\n}\n\ntype Query {\n    tasks: [Task!]!\n}\n\ntype Mutation {\n    createTask(name: String!): Task!\n}\n
\n\n

Now let's run the generation and write resolvers in Go:

\n\n
package main\n\nimport (\n    "log"\n    "net/http"\n    "github.com/99designs/gqlgen/graphql/handler"\n    "github.com/99designs/gqlgen/graphql/playground"\n)\n\n// Assuming the generated code already exists\ntype Resolver struct {\n    tasks []Task\n    mu    sync.Mutex\n}\n\nfunc (r *Resolver) Tasks(ctx context.Context) ([]Task, error) {\n    r.mu.Lock()\n    defer r.mu.Unlock()\n    return r.tasks, nil\n}\n\nfunc (r *Resolver) CreateTask(ctx context.Context, name string) (*Task, error) {\n    r.mu.Lock()\n    defer r.mu.Unlock()\n                

Blogs

Book Recommendations