SoFunction
Updated on 2025-03-05

Go REST API design pattern and anti-pattern example analysis

REST API design pattern

RESTful API has become the de facto standard for building modern network applications. They allow for a flexible and scalable architecture that can be easily consumed by a wide range of clients. However, designing a robust and maintainable REST API is challenging, especially for new developers.

1. Resource-oriented architecture (ROA)

Resource-Oriented Architecture (ROA) is a design pattern that emphasizes the importance of resources in the RESTful API. Resources are key components of the RESTful API and they should be designed in ways that are easy to consume and operate.

One way to implement ROA in Golang is to usegorilla/muxPackets are routed. Here is an example:

r := ()
("/users/{id}", getUser).Methods("GET")
("/users", createUser).Methods("POST")
("/users/{id}", updateUser).Methods("PUT")
("/users/{id}", deleteUser).Methods("DELETE")

In Open API Schema, you can usepathParameters to define the resource. Here is an example:

paths:
 /users/{id}:
 get:
 …
 put:
 …
 delete:
 …
 /users:
 post:
 …

2. HATEOAS

Hypermedia as the engine of application state (HATEOAS) is a design pattern that allows customers to dynamically browse the RESTful API. The API provides hypermedia links that customers can follow to discover and interact with resources.

To implement it in GoLangHATEOAS, you can usego-jsonapiBag. Here is an example:

type User struct {
 ID string `json:"id"`
 Name string `json:"name"`
 Links *Links `json:"links,omitempty"`
}
type Links struct {
 Self *Link `json:"self,omitempty"`
}
type Link struct {
 Href string `json:"href,omitempty"`
}
func getUser(w , r *) {
 userID := (r)["id"]
 user := User{ID: userID, Name: "John Doe"}
  = &Links{
 Self: &Link{Href: ("/users/%s", userID)},
 }
 (w, &user)
}

In Open API Schema, you can uselinksParameters to define hypermedia links. Here is an example:

paths:
 /users/{id}:
 get:
 responses:
 '200':
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/User'
 links:
 self:
 href: '/users/{id}'

REST API anti-mode

A stylist API

Remote Procedure Call (RPC) style API is a common anti-pattern in RESTful API design. RPC-style APIs expose methods of mapping directly to underlying implementations rather than focusing on resources.

Here is an example of an RPC-style API in GoLang:

func getUser(w , r *) {
 userID := ("id")
 user := (userID)
 (w).Encode(user)
}

In Open API Schema, you can useoperationIdParameters to define RPC-style API. Here is an example:

paths:
 /users:
 get:
 operationId: getUser

2. Excessive engineering design

Overengineering is another common anti-pattern in RESTful API design. Over-design occurs when developers try to predict every possible use case and build a complex API to adapt to them.

Here is an example of overengineering in Golang:

func getUser(w , r *) {
 userID := (r)["id"]
 user, err := (userID)
 if err != nil {
 handleError(w, err)
 return
 }
 (w).Encode(user)
}
func createUser(w , r *) {
 var user User
 err := ().Decode(&user)
 if err != nil {
 handleError(w, err)
 return
 }
  = ().String()
  = ()
  = ()
 err = (user)
 if err != nil {
 handleError(w, err)
 return
 }
 (w).Encode(user)
}
func updateUser(w , r *) {
 userID := (r)["id"]
 var user User
 err := ().Decode(&user)
 if err != nil {
 handleError(w, err)
 return
 }
  = userID
  = ()
 err = (user)
 if err != nil {
 handleError(w, err)
 return
 }
 (w).Encode(user)
}
func deleteUser(w , r *) {
 userID := (r)["id"]
 err := (userID)
 if err != nil {
 handleError(w, err)
 return
 }
 ()
}
func handleError(w , err error) {
 ()
 (w, err. Error())
}

In Open API Schema, you can usex-go-genieExtension defines overengineering. Here is an example:

paths:
 /users/{id}:
   get:
     x-go-genie:
       serviceName: UserService
       methodName: GetUser
   put:
     x-go-genie:
       serviceName: UserService
       methodName: UpdateUser
   delete:
     x-go-genie:
       serviceName: UserService
       methodName: DeleteUser
 /users:
   post:
     x-go-genie:
       serviceName: UserService
       methodName: CreateUser

Summarize

Designing a RESTful API that is both robust and maintainable can be challenging, but by following best practices and avoiding common anti-patterns, developers can create APIs that are easy to consume and operate. In this article, we explore some common REST API design patterns and anti-patterns, and provide code snippets of GoLang and Open API Schema to help illustrate these concepts.

The above is the detailed analysis of go REST API design pattern and anti-mode examples. For more information about go REST API design pattern anti-mode, please pay attention to my other related articles!