This article has participated in the call for good writing activities, click to view: back end, big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!
RESTful API
EST is Representational State Transfer (REST), a design and development method for network applications that reduces development complexity and improves system scalability. (quoted from Baidu Baike).
HTTP Method
- Back in HTTP 0.9, there was only one GET method, which was an idempotent method used to GET a resource on the server;
- HTTP 1.0 added the HEAD and POST methods, the most common of which is the POST method, which is generally used to submit a resource to the server.
- In HTTP1.1, several methods have been added. That adds up to nine.
What they do:
- The GET method requests a representation of a specified resource, and requests using GET should only be used to GET data.
- The HEAD method is used to request a response that is identical to the response of the GET request, but without the response body.
- The POST method is used to submit an entity to a specified resource, often resulting in a state change or side effect on the server.
- The PUT method is used to request the payload to replace all current representations of the target resource.
- The DELETE method is used to DELETE a specified resource.
- The CONNECT method is used to establish a tunnel to a server identified by the target resource.
- The OPTIONS method is used to describe the communication OPTIONS of the target resource.
- The TRACE method is used to perform a message loopback test along the path to the target resource.
- The PATCH method is used to apply partial changes to the resource.
In RESTful apis, the following five HTTP methods are used:
- GET: reads resources on the server.
- POST: creates resources on the server.
- PUT: updates or replaces resources on the server.
- DELETE: deletes resources on the server.
- PATCH: updates/modifies a portion of a resource.
A simple RESTful API
Golang provides a built-in NET/HTTP package to handle these HTTP requests, making it easy to develop an HTTP service.
Example:
package main
import (
"fmt"
"net/http"
)
func main(a) {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(": 8080".nil)}func handleUsers(w http.ResponseWriter, r *http.Request){
fmt.Fprintln(w,"ID: 1, Name: zhang SAN")
fmt.Fprintln(w,"ID: 2, Name: li si")
fmt.Fprintln(w,"ID: 3, the Name: fifty.")}Copy the code
After running the program, enter http://localhost:8080/users in your browser, you can see the following information:
ID:1Name: zhang SAN ID:2Name: li si ID:3, Name: fiftyCopy the code
In this example, not only GET can be used for access, but also POST, PUT, and so on. Let’s improve the example to make it conform to the specifications of the RESTful API:
package main
import (
"fmt"
"net/http"
)
func main(a) {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(": 8080".nil)}func handleUsers(w http.ResponseWriter, r *http.Request){
switch r.Method {
case "GET":
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w,"ID: 1, Name: zhang SAN")
fmt.Fprintln(w,"ID: 2, Name: li si")
fmt.Fprintln(w,"ID: 3, the Name: fifty.")
default:
w.WriteHeader(http.StatusNotFound)
fmt.Fprintln(w,"not found")}}Copy the code
We added to the handleUsers function that only gets information about all users when the GET method is used, otherwise returns not found.
RESTful JSON API
In the project interface, the data will mostly be transferred in JSON format. Again, modify the example to return json format:
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main(a) {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(": 8080".nil)}// Data source to simulate data in MySQL
var users = []User{
{ID: 1,Name: "Zhang"},
{ID: 2,Name: "Bill"},
{ID: 3,Name: "Fifty"}},func handleUsers(w http.ResponseWriter, r *http.Request){
switch r.Method {
case "GET":
users,err:=json.Marshal(users)
iferr! =nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w,"{\"message\": \""+err.Error()+"\"}")}else {
w.WriteHeader(http.StatusOK)
w.Write(users)
}
default:
w.WriteHeader(http.StatusNotFound)
fmt.Fprint(w,"{\"message\": \"not found\"}")}}/ / user
type User struct {
ID int
Name string
}
Copy the code
Running results:
[{"ID":1."Name":"Zhang"}, {"ID":2."Name":"Bill"}, {"ID":3."Name":"Fifty"}]
Copy the code
This time, we create a new User structure, use the Users slice to store all users, and return it as a JSON array in the handleUsers function.
Gin framework
The net/ HTTP package used in the Go language is relatively simple to write, but it also has many disadvantages:
- You cannot register specific handlers for request methods (POST, GET, and so on) separately;
- Path variable parameters are not supported;
- Path cannot be automatically calibrated;
- General performance, poor scalability;
- …
Based on the above shortcomings, we can use other Golang Web frameworks, such as the Gin framework introduced today.
Introducing Gin Framework
Gin framework is an open source Web framework on Github that encapsulates many of the functions required for Web development and is very high-performance, making it easy to write RESTful apis. Gin framework is actually a module, which can be introduced by Go Mod:
- Download and install the Gin framework
go get -u github.com/gin-gonic/gin 2. Import in the Go language code using the import “github.com/gin-gonic/gin”
Using Gin Framework
We use the Gin framework to rewrite the above example:
package main
import "github.com/gin-gonic/gin"
func main(a) {
r := gin.Default()
r.GET("/users", listUser)
r.Run(": 8080")}func listUser(c *gin.Context) {
c.JSON(200, users)
}
// Data source to simulate data in MySQL
var users = []User{
{ID: 1, Name: "Zhang"},
{ID: 2, Name: "Bill"},
{ID: 3, Name: "Fifty"}},/ / user
type User struct {
ID int
Name string
}
Copy the code
In contrast to net/ HTTP packages, the Gin framework code is very simple, using the GET method to create a service that only handles the HTTP GET method, and using the C. SON method to output data in JSON format. Start the HTTP service using the Run method and listen on port 8080. Run the Gin example, enter http://localhost:8080/users in the browser, you can see and through the.net/HTTP packet implementation effect is the same.
Get a user
Access to a user’s information, we use the GET method, design the URL format for: http://localhost:8080/users/1 in the URL number 1 for a user id, we GET a specified by id users:
func main(a) {
// omit other unchanged code
r.GET("/users/:id", getUser)
}
func getUser(c *gin.Context) {
id := c.Param("id")
var user User
found := false
// A database - like SQL query
for _, u := range users {
if strings.EqualFold(id, strconv.Itoa(u.ID)) {
user = u
found = true
break}}if found {
c.JSON(200, user)
} else {
c.JSON(404, gin.H{
"message": "User does not exist",}}}Copy the code
In the Gin framework, colons are used to indicate Path Path parameters, such as: ID in the example, and then c. param (” ID “) is used to obtain the ID value of the user to be queried. Run the example, to access the address http://localhost:8080/users/1, you can obtain user ID is 1: {” ID “: 1,” Name “:” * * “}
Add a user
Add a user’s URL is: http://localhost:8080/users send data to the URL, you can add a user.
func main(a) {
// omit other unchanged code
r.POST("/users", createUser)
}
func createUser(c *gin.Context) {
name := c.DefaultPostForm("name"."")
ifname ! ="" {
u := User{ID: len(users) + 1, Name: name}
users = append(users, u)
c.JSON(http.StatusCreated,u)
} else {
c.JSON(http.StatusOK, gin.H{
"message": "Please enter user name",}}}Copy the code
The logic for adding a User is to get the name value uploaded by the client, generate a User User, and finally store it in the Users collection. Delete from curl: delete from curl: delete from curl
curl -X POST -d 'name = clean' http://localhost:8080/users
{"ID":4."Name":"Clean"}
Copy the code
You can see that the new user is successfully added and the new user and assigned ID are returned.