Movatterモバイル変換


[0]ホーム

URL:


  1. Documentation
  2. Tutorials
  3. Tutorial: Developing a RESTful API with Go and Gin

Tutorial: Developing a RESTful API with Go and Gin

This tutorial introduces the basics of writing a RESTful web service API with Goand theGin Web Framework (Gin).

You’ll get the most out of this tutorial if you have a basic familiarity with Goand its tooling. If this is your first exposure to Go, please seeTutorial: Get started with Gofor a quick introduction.

Gin simplifies many coding tasks associated with building web applications,including web services. In this tutorial, you’ll use Gin to route requests,retrieve request details, and marshal JSON for responses.

In this tutorial, you will build a RESTful API server with two endpoints. Yourexample project will be a repository of data about vintage jazz records.

The tutorial includes the following sections:

  1. Design API endpoints.
  2. Create a folder for your code.
  3. Create the data.
  4. Write a handler to return all items.
  5. Write a handler to add a new item.
  6. Write a handler to return a specific item.

Note: For other tutorials, seeTutorials.

To try this as an interactive tutorial you complete in Google Cloud Shell,click the button below.

Open in Cloud Shell

Prerequisites

Design API endpoints

You’ll build an API that provides access to a store selling vintage recordingson vinyl. So you’ll need to provide endpoints through which a client can getand add albums for users.

When developing an API, you typically begin by designing the endpoints. YourAPI’s users will have more success if the endpoints are easy to understand.

Here are the endpoints you’ll create in this tutorial.

/albums

/albums/:id

Next, you’ll create a folder for your code.

Create a folder for your code

To begin, create a project for the code you’ll write.

  1. Open a command prompt and change to your home directory.

    On Linux or Mac:

    $ cd

    On Windows:

    C:\> cd %HOMEPATH%
  2. Using the command prompt, create a directory for your code calledweb-service-gin.

    $ mkdir web-service-gin$ cd web-service-gin
  3. Create a module in which you can manage dependencies.

    Run thego mod init command, giving it the path of the module your codewill be in.

    $ go mod init example/web-service-gingo: creating new go.mod: module example/web-service-gin

    This command creates a go.mod file in which dependencies you add will belisted for tracking. For more about naming a module with a module path, seeManaging dependencies.

Next, you’ll design data structures for handling data.

Create the data

To keep things simple for the tutorial, you’ll store data in memory. A moretypical API would interact with a database.

Note that storing data in memory means that the set of albums will be lost eachtime you stop the server, then recreated when you start it.

Write the code

  1. Using your text editor, create a file called main.go in the web-servicedirectory. You’ll write your Go code in this file.

  2. Into main.go, at the top of the file, paste the following package declaration.

    package main

    A standalone program (as opposed to a library) is always in packagemain.

  3. Beneath the package declaration, paste the following declaration of analbum struct. You’ll use this to store album data in memory.

    Struct tags such asjson:"artist" specify what a field’s name should bewhen the struct’s contents are serialized into JSON. Without them, the JSONwould use the struct’s capitalized field names – a style not as common inJSON.

    // album represents data about a record album.type album struct {    ID     string  `json:"id"`    Title  string  `json:"title"`    Artist string  `json:"artist"`    Price  float64 `json:"price"`}
  4. Beneath the struct declaration you just added, paste the following slice ofalbum structs containing data you’ll use to start.

    // albums slice to seed record album data.var albums = []album{    {ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},    {ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},    {ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},}

Next, you’ll write code to implement your first endpoint.

Write a handler to return all items

When the client makes a request atGET /albums, you want to return all thealbums as JSON.

To do this, you’ll write the following:

Note that this is the reverse of how they’ll be executed at runtime, but you’readding dependencies first, then the code that depends on them.

Write the code

  1. Beneath the struct code you added in the preceding section, paste thefollowing code to get the album list.

    ThisgetAlbums function creates JSON from the slice ofalbum structs,writing the JSON into the response.

    // getAlbums responds with the list of all albums as JSON.func getAlbums(c *gin.Context) {    c.IndentedJSON(http.StatusOK, albums)}

    In this code, you:

    • Write agetAlbums function that takes agin.Contextparameter. Note that you could have given this function any name – neitherGin nor Go require a particular function name format.

      gin.Context is the most important part of Gin. It carries requestdetails, validates and serializes JSON, and more. (Despite the similarname, this is different from Go’s built-incontext package.)

    • CallContext.IndentedJSONto serialize the struct into JSON and add it to the response.

      The function’s first argument is the HTTP status code you want to send tothe client. Here, you’re passing theStatusOKconstant from thenet/http package to indicate200 OK.

      Note that you can replaceContext.IndentedJSON with a call toContext.JSONto send more compact JSON. In practice, the indented form is much easier towork with when debugging and the size difference is usually small.

  2. Near the top of main.go, just beneath thealbums slice declaration, pastethe code below to assign the handler function to an endpoint path.

    This sets up an association in whichgetAlbums handles requests to the/albums endpoint path.

    func main() {    router := gin.Default()    router.GET("/albums", getAlbums)    router.Run("localhost:8080")}

    In this code, you:

    • Initialize a Gin router usingDefault.

    • Use theGETfunction to associate theGET HTTP method and/albums path with a handlerfunction.

      Note that you’re passing thename of thegetAlbums function. This isdifferent from passing theresult of the function, which you would do bypassinggetAlbums() (note the parenthesis).

    • Use theRunfunction to attach the router to anhttp.Server and start the server.

  3. Near the top of main.go, just beneath the package declaration, import thepackages you’ll need to support the code you’ve just written.

    The first lines of code should look like this:

    package mainimport (    "net/http"    "github.com/gin-gonic/gin")
  4. Save main.go.

Run the code

  1. Begin tracking the Gin module as a dependency.

    At the command line, usego getto add the github.com/gin-gonic/gin module as a dependency for your module.Use a dot argument to mean “get dependencies for code in the currentdirectory.”

    $ go get .go get: added github.com/gin-gonic/gin v1.7.2

    Go resolved and downloaded this dependency to satisfy theimportdeclaration you added in the previous step.

  2. From the command line in the directory containing main.go, run the code.Use a dot argument to mean “run code in the current directory.”

    $ go run .

    Once the code is running, you have a running HTTP server to which you cansend requests.

  3. From a new command line window, usecurl to make a request to your runningweb service.

    $ curl http://localhost:8080/albums

    The command should display the data you seeded the service with.

    [        {                "id": "1",                "title": "Blue Train",                "artist": "John Coltrane",                "price": 56.99        },        {                "id": "2",                "title": "Jeru",                "artist": "Gerry Mulligan",                "price": 17.99        },        {                "id": "3",                "title": "Sarah Vaughan and Clifford Brown",                "artist": "Sarah Vaughan",                "price": 39.99        }]

You’ve started an API! In the next section, you’ll create another endpoint withcode to handle aPOST request to add an item.

Write a handler to add a new item

When the client makes aPOST request at/albums, you want to add the albumdescribed in the request body to the existing albums’ data.

To do this, you’ll write the following:

Write the code

  1. Add code to add albums data to the list of albums.

    Somewhere after theimport statements, paste the following code. (The endof the file is a good place for this code, but Go doesn’t enforce the orderin which you declare functions.)

    // postAlbums adds an album from JSON received in the request body.func postAlbums(c *gin.Context) {    var newAlbum album    // Call BindJSON to bind the received JSON to    // newAlbum.    if err := c.BindJSON(&newAlbum); err != nil {        return    }    // Add the new album to the slice.    albums = append(albums, newAlbum)    c.IndentedJSON(http.StatusCreated, newAlbum)}

    In this code, you:

    • UseContext.BindJSONto bind the request body tonewAlbum.
    • Append thealbum struct initialized from the JSON to thealbumsslice.
    • Add a201 status code to the response, along with JSON representingthe album you added.
  2. Change yourmain function so that it includes therouter.POST function,as in the following.

    func main() {    router := gin.Default()    router.GET("/albums", getAlbums)    router.POST("/albums", postAlbums)    router.Run("localhost:8080")}

    In this code, you:

    • Associate thePOST method at the/albums path with thepostAlbumsfunction.

      With Gin, you can associate a handler with an HTTP method-and-pathcombination. In this way, you can separately route requests sent to asingle path based on the method the client is using.

Run the code

  1. If the server is still running from the last section, stop it.

  2. From the command line in the directory containing main.go, run the code.

    $ go run .
  3. From a different command line window, usecurl to make a request to yourrunning web service.

    $ curl http://localhost:8080/albums \    --include \    --header "Content-Type: application/json" \    --request "POST" \    --data '{"id": "4","title": "The Modern Sound of Betty Carter","artist": "Betty Carter","price": 49.99}'

    The command should display headers and JSON for the added album.

    HTTP/1.1 201 CreatedContent-Type: application/json; charset=utf-8Date: Wed, 02 Jun 2021 00:34:12 GMTContent-Length: 116{    "id": "4",    "title": "The Modern Sound of Betty Carter",    "artist": "Betty Carter",    "price": 49.99}
  4. As in the previous section, usecurl to retrieve the full list of albums,which you can use to confirm that the new album was added.

    $ curl http://localhost:8080/albums \    --header "Content-Type: application/json" \    --request "GET"

    The command should display the album list.

    [        {                "id": "1",                "title": "Blue Train",                "artist": "John Coltrane",                "price": 56.99        },        {                "id": "2",                "title": "Jeru",                "artist": "Gerry Mulligan",                "price": 17.99        },        {                "id": "3",                "title": "Sarah Vaughan and Clifford Brown",                "artist": "Sarah Vaughan",                "price": 39.99        },        {                "id": "4",                "title": "The Modern Sound of Betty Carter",                "artist": "Betty Carter",                "price": 49.99        }]

In the next section, you’ll add code to handle aGET for a specific item.

Write a handler to return a specific item

When the client makes a request toGET /albums/[id], you want to return thealbum whose ID matches theid path parameter.

To do this, you will:

Write the code

  1. Beneath thepostAlbums function you added in the preceding section, pastethe following code to retrieve a specific album.

    ThisgetAlbumByID function will extract the ID in the request path, thenlocate an album that matches.

    // getAlbumByID locates the album whose ID value matches the id// parameter sent by the client, then returns that album as a response.func getAlbumByID(c *gin.Context) {    id := c.Param("id")    // Loop over the list of albums, looking for    // an album whose ID value matches the parameter.    for _, a := range albums {        if a.ID == id {            c.IndentedJSON(http.StatusOK, a)            return        }    }    c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})}

    In this code, you:

    • UseContext.Paramto retrieve theid path parameter from the URL. When you map thishandler to a path, you’ll include a placeholder for the parameter in thepath.

    • Loop over thealbum structs in the slice, looking for one whoseIDfield value matches theid parameter value. If it’s found, you serializethatalbum struct to JSON and return it as a response with a200 OKHTTP code.

      As mentioned above, a real-world service would likely use a databasequery to perform this lookup.

    • Return an HTTP404 error withhttp.StatusNotFoundif the album isn’t found.

  2. Finally, change yourmain so that it includes a new call torouter.GET,where the path is now/albums/:id, as shown in the following example.

    func main() {    router := gin.Default()    router.GET("/albums", getAlbums)    router.GET("/albums/:id", getAlbumByID)    router.POST("/albums", postAlbums)    router.Run("localhost:8080")}

    In this code, you:

    • Associate the/albums/:id path with thegetAlbumByID function. InGin, the colon preceding an item in the path signifies that the item isa path parameter.

Run the code

  1. If the server is still running from the last section, stop it.

  2. From the command line in the directory containing main.go, run the code tostart the server.

    $ go run .
  3. From a different command line window, usecurl to make a request to yourrunning web service.

    $ curl http://localhost:8080/albums/2

    The command should display JSON for the album whose ID you used. If thealbum wasn’t found, you’ll get JSON with an error message.

    {        "id": "2",        "title": "Jeru",        "artist": "Gerry Mulligan",        "price": 17.99}

Conclusion

Congratulations! You’ve just used Go and Gin to write a simple RESTful webservice.

Suggested next topics:

Completed code

This section contains the code for the application you build with this tutorial.

package mainimport (    "net/http"    "github.com/gin-gonic/gin")// album represents data about a record album.type album struct {    ID     string  `json:"id"`    Title  string  `json:"title"`    Artist string  `json:"artist"`    Price  float64 `json:"price"`}// albums slice to seed record album data.var albums = []album{    {ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},    {ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},    {ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},}func main() {    router := gin.Default()    router.GET("/albums", getAlbums)    router.GET("/albums/:id", getAlbumByID)    router.POST("/albums", postAlbums)    router.Run("localhost:8080")}// getAlbums responds with the list of all albums as JSON.func getAlbums(c *gin.Context) {    c.IndentedJSON(http.StatusOK, albums)}// postAlbums adds an album from JSON received in the request body.func postAlbums(c *gin.Context) {    var newAlbum album    // Call BindJSON to bind the received JSON to    // newAlbum.    if err := c.BindJSON(&newAlbum); err != nil {        return    }    // Add the new album to the slice.    albums = append(albums, newAlbum)    c.IndentedJSON(http.StatusCreated, newAlbum)}// getAlbumByID locates the album whose ID value matches the id// parameter sent by the client, then returns that album as a response.func getAlbumByID(c *gin.Context) {    id := c.Param("id")    // Loop through the list of albums, looking for    // an album whose ID value matches the parameter.    for _, a := range albums {        if a.ID == id {            c.IndentedJSON(http.StatusOK, a)            return        }    }    c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})}
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.Learn more.

[8]ページ先頭

©2009-2025 Movatter.jp