Welcome to this lesson focusing on enhancing your skills in interacting with RESTful APIs by updating and deleting resources. In previous lessons, you learned how to retrieve and create resources using the GET
and POST
methods. Now, you will explore the PUT
, PATCH
, and DELETE
methods, which are crucial for modifying existing resources or removing them when they are no longer needed.
To effectively manage resources within an API, it's essential to understand how to use the following methods:
-
PUT: This method is used for completely updating a resource. You replace the current resource with the new data you provide in the request body. For example, if you're updating a to-do item, you'll include all the new details of the item in the body of the request and specify the resource ID in the request path to indicate which item you are updating.
-
PATCH: Use this method to make partial updates to a resource. You only need to include the specific fields you're updating in the request body. For instance, if you're only changing the description of a to-do item, you'll pass just the new description in the body. The resource ID is specified in the request path to identify which item is being modified.
-
DELETE: This straightforward method removes a resource from the server. You specify which resource to delete by including its identifier in the request path. No request body is needed since you're not sending any data, just instructing the server to remove the resource corresponding to that ID.
Successful requests using these methods typically return status codes of 200
(OK) or 204
(No Content). A 200
status code means the operation was successful and also returns content, such as a representation of the updated resource. In contrast, a 204
status code indicates success but with no content returned, meaning the server successfully processed the request but isn't providing any additional information. These methods are crucial for performing full CRUD (Create, Read, Update, Delete) functionality in API management.
Before executing HTTP requests, let's set up our Go environment by importing the necessary Go packages and defining the base URL for our API interactions:
Go1package main 2 3import ( 4 "bytes" 5 "fmt" 6 "io" 7 "net/http" 8) 9 10// Base URL for the API 11const baseUrl = "http://localhost:8000"
With this setup in place, you're well-prepared to explore PUT
, PATCH
, and DELETE
operations for resource management.
So far, we’ve used http.Get
and http.Post
to interact with APIs. These functions work well for simple requests, but sometimes we need more control—especially when using PUT, PATCH, and DELETE, which don’t have built-in helper functions in Go.
For these cases, Go provides the http.NewRequest
function, which allows us to create a customizable HTTP request.
- Supports all HTTP methods (
GET
,POST
,PUT
,PATCH
,DELETE
, etc.). - Allows us to set headers (like
"Content-Type": "application/json"
). - Gives more control over the request body.
Here’s an example of how to create a request using http.NewRequest
:
Go1req, err := http.NewRequest(http.MethodPut, "http://example.com/resource", nil) 2if err != nil { 3 log.Fatalf("Failed to create request: %v", err) 4}
Once the request is created, we send it using an http.Client:
Go1client := &http.Client{} 2resp, err := client.Do(req) 3if err != nil { 4 log.Fatalf("Failed to send request: %v", err) 5}
Since PUT, PATCH, and DELETE require us to send structured data, we use http.NewRequest to define these requests, then send them using an http.Client.
Next, let’s see http.NewRequest in action as we update resources with the PUT method.
The PUT
method is utilized when you need to update an entire resource. Imagine you have a to-do item that needs a complete overhaul, such as updating the task description, adding more details, or marking it as completed. The PUT
request replaces the current resource representation with the new one you provide.
Here's an example of how to send a PUT
request to update a to-do item:
Go1func updateTodoWithPut(todoID int) { 2 // Updated todo data for PUT 3 updatedTodo := `{ 4 "title": "Buy groceries and snacks", 5 "done": true, 6 "description": "Milk, eggs, bread, coffee, and chips." 7 }` 8 9 // Send PUT request 10 request, err := http.NewRequest(http.MethodPut, baseUrl+"/todos/"+fmt.Sprint(todoID), bytes.NewBufferString(updatedTodo)) 11 if err != nil { 12 fmt.Println("Error creating request:", err) 13 return 14 } 15 request.Header.Set("Content-Type", "application/json") 16 17 client := &http.Client{} 18 response, err := client.Do(request) 19 if err != nil { 20 fmt.Println("Error sending request:", err) 21 return 22 } 23 24 // Check if the request was successful 25 if response.StatusCode == http.StatusOK { 26 body, _ := io.ReadAll(response.Body) 27 fmt.Println("Todo updated successfully with PUT!") 28 fmt.Println(string(body)) 29 } else { 30 // Handle potential errors 31 fmt.Println("Error updating the todo with PUT") 32 fmt.Printf("Status Code: %d\n", response.StatusCode) 33 body, _ := io.ReadAll(response.Body) 34 fmt.Println("Error Details:", string(body)) 35 } 36}
In this code, we specify the complete new data for the to-do item and send the request using Go's http.NewRequest
method. Upon receiving a 200
status code using http.StatusOK
, you know the update was successful, and you can print the new representation of the to-do item. It's important to note that for our API, a PUT
request requires all fields (title
, description
, and done
) to be provided. If any field is missing, the request will fail and return a status code of 400
. In cases where you only need to update specific fields, rather than the entire resource, the PATCH
method is more suitable.
Unlike PUT
, the PATCH
method is specifically designed for partial updates. When you need to modify only a specific field of a resource, PATCH
ensures system efficiency and data integrity without the need to send a full representation.
Here's an example of performing a PATCH
request on a resource:
Go1func updateTodoWithPatch(todoID int) { 2 // Partial updated data 3 patchData := `{ 4 "description": "Updated description" 5 }` 6 7 // Send PATCH request 8 request, err := http.NewRequest(http.MethodPatch, baseUrl+"/todos/"+fmt.Sprint(todoID), bytes.NewBufferString(patchData)) 9 if err != nil { 10 fmt.Println("Error creating request:", err) 11 return 12 } 13 request.Header.Set("Content-Type", "application/json") 14 15 client := &http.Client{} 16 response, err := client.Do(request) 17 if err != nil { 18 fmt.Println("Error sending request:", err) 19 return 20 } 21 22 // Check if the request was successful 23 if response.StatusCode == http.StatusOK { 24 body, _ := io.ReadAll(response.Body) 25 fmt.Println("Todo updated successfully with PATCH!") 26 fmt.Println(string(body)) 27 } else { 28 // Handle potential errors 29 fmt.Println("Error updating the todo with PATCH") 30 fmt.Printf("Status Code: %d\n", response.StatusCode) 31 body, _ := io.ReadAll(response.Body) 32 fmt.Println("Error Details:", string(body)) 33 } 34}
In this scenario, only the description
field is updated. After sending the PATCH
request using Go's http.NewRequest
method, we can check the response status code to confirm success. Successful updates with a status code of 200
allow you to view the updated resource fields, while any errors are managed by inspecting and printing error details.
After learning how to update resources using PUT
and PATCH
, let's move on to deleting resources with the DELETE
method. This method is straightforward - it's used to remove a resource from the server, which is important for keeping your data clean and relevant.
Here's how you can perform a DELETE
request:
Go1func deleteTodoWithDelete(todoID int) { 2 // Send DELETE request 3 request, err := http.NewRequest(http.MethodDelete, baseUrl+"/todos/"+fmt.Sprint(todoID), nil) 4 if err != nil { 5 fmt.Println("Error creating request:", err) 6 return 7 } 8 9 client := &http.Client{} 10 response, err := client.Do(request) 11 if err != nil { 12 fmt.Println("Error sending request:", err) 13 return 14 } 15 16 // Check if the request was successful 17 if response.StatusCode == http.StatusNoContent { 18 fmt.Println("Todo deleted successfully!") 19 } else { 20 // Handle potential errors 21 fmt.Println("Error deleting the todo") 22 fmt.Printf("Status Code: %d\n", response.StatusCode) 23 body, _ := io.ReadAll(response.Body) 24 fmt.Println("Error Details:", string(body)) 25 } 26}
In this example, we're sending a DELETE
request to remove a specific to-do item by specifying its ID in the request path. When the server successfully deletes the resource, you will typically receive a 204
status code using http.StatusNoContent
. This code means "No Content," indicating that the deletion was successful, but there's no additional data to send back.
However, it's important to note that some services might return a 200
status code along with some content, such as a message. This can vary depending on how the service is designed, so always check the API documentation for specifics on how it handles deletions.
This lesson provided you with a comprehensive understanding of the PUT
, PATCH
, and DELETE
methods, enhancing your ability to modify and manage resources through API interactions using Go. You learned how to update complete resources with PUT
, make partial modifications with PATCH
, and delete resources using DELETE
. Understanding these operations is key to mastering CRUD functionality in RESTful API management using Go.
As you proceed to the practice exercises, you're encouraged to apply these concepts to reinforce your understanding and learn through practice. Each operation is a building block towards becoming proficient in interacting with APIs using Go. Keep up the great work as you progress through the exercises, further cementing your knowledge and skills in API resource management!