How to create a RESTful interface only from the Go language standard library

Source: Internet
Author: User
Tags email string key string random seed sprintf
This is a creation in Article, where the information may have evolved or changed. Ryan Macchu December 9, 2017 go is a fairly new language and has gained more and more attention in recent years. It's very powerful and has great tools to design a fast and efficient API interface. Although there are already many libraries that can create an API interface, such as [Go Buffalo] (https://gobuffalo.io/) and [Goa] (https://goa.design/), however, if you can do this in addition to the database and cache connectors, Just using the standard library to create it will undoubtedly be very interesting. In this blog post, I'll analyze how to use the Go language standard library to create an endpoint (Endpoint). The entire API (including multiple endpoint (Endpoint)) code on my GitHub [Golang-standard-lib-rest-api] (https://github.com/rymccue/ GOLANG-STANDARD-LIB-REST-API) Library. # # Getting Started in the first step, you need to plan the entire directory structure and create directories for controllers, requests, database migrations, database queries (repositories), helper tools, and so on. The project directory structure is as follows: "Controllersdatabasemodelsrepositoriesrequestsroutesutils" After creating these directories, let's create the **main.go** file. This is the first source code that was created, so it will be written according to our ideas before we create the surrounding related packages. We need main.go file to do the following things: 1. Create a database connection 2. Create a dedicated cache connection for authentication 3. Create a mux4. Load all the Controllers 5. Use MUX and controller to create Route 6. Start server ' Godb, err: = database. Connect (OS. Getenv ("Pguser"), OS. Getenv ("Pgpass"), OS. Getenv ("PGDB"), OS. Getenv ("PGHOST"), OS. Getenv ("PGPORT")) if err! = Nil {log. Fatal (err)}cache: = &caching. Redis{client:caching. Connect (OS. Getenv ("Redis_addr"), OS. Getenv ("Redis_password"), 0),}usercontroller: = Controllers. Newusercontroller (db, Cache) Jobcontroller: = controllers. Newjobcontroller (db, Cache) Mux: = http. Newservemux () routes. Createroutes (MUX, Usercontroller, Jobcontroller) If err: = http. Listenandserve (": 8000", MUX); Err! = Nil {log. Fatal (Err)} "We want the code to look like the above, create a database and cache connection, load the controller, connect the controller to the route, and finally start the server." Now that we have a well-planned master portal file, let's create the library we need to use. The # # Connection tool lets us start with a relatively simple database and caching tool. The **database.go** file simply creates a connection string and opens a connection. **utils/database/database.go** ' Gofunc Connect (user, password, dbname, host, port string) (*sql. DB, error) {connstr: = FMT. Sprintf ("user=%s password=%s dbname=%s host=%s port=%s", User, password, dbname, host, Port) return SQL. Open ("Postgres", ConnStr)} "cache package takes a little effort, we use an interface to abstract." That way, if you decide to use a different caching service, the code changes are straightforward. **utils/caching/caching.go** This can be modified according to your needs, but in the present case, a good cache interface is as follows: "' Gotype cache interface {Get (key string) (string , error) Set (key, value string, expiration time. Duration) Error} ' now creates a struct to implement this interface: ' Gotype Redis struct {Client *redis. Client}func (R *redis) Get (Key string) (StrinG, error) {return R.client.get (key). Result ()}func (R *redis) Set (key, value string, expiration time. Duration) Error {return R.client.set (key, value, expiration). ERR ()} ' ' Finally, a function returned to the Redis client. "' Gofunc Connect (addr, password string, db int) *redis. Client {return Redis. Newclient (&redis. options{addr:addr, Password:password, Db:db,})} ' # # User controller is good, caching and database tools have been completed. Now start doing some interesting development by defining the route that you need first. We need two controllers, one user and one working controller, and each controller has some endpoints (Endpoint). Before we actually write the controller, let's put these ideas and designs on paper. "User controllerpost/registerpost/login" "Job controllerget/job/{id}put/job/{id}delete/job/{id}post/jobget/ Feed "To do this, we now know which endpoints are needed (Endpoint). Let's create the user controller and register the endpoint (Endpoint). If you look at **main.go**, you'll find a way to call **newusercontroller** and let's start from there. We want to be able to access the cache and the database in the user controller, so we need to pass these two objects to the function. The struct needs to be like this, so we can call the database and the cache within the Controller method, such as **usercontroller.db** and **usercontroller.cache**. Note that the cache is an interface, so we can replace its implementation at any time. "' Gotype usercontroller struct {DB *sql. Dbcache caching. The cache} ' **newusercontroller** function should simply return the **usercontroller** struct with the database and cache objects. "' GofuNC newusercontroller (DB *sql. DB, C caching. Cache) *usercontroller {return &usercontroller{db:db,cache:c,}} ' # # Registration Endpoint (Endpoint) Great, we have the user controller, now to add a method. Registration is a very basic feature, so let's implement it. Let's take it one step at a way. First, we only need the POST request of this endpoint (Endpoint), so first check if it is the post (HTTP) method, and if not, return a not found state to the client. "' Gofunc (JC *usercontroller) Register (w http. Responsewriter, R *http. Request) {if r.method! = "POST" {http. Error (W, "not Found", HTTP. Statusnotfound) return} ' after the check passes, the requested data body needs to be decoded to obtain the requested data. If there is a problem with the data body, send the bad request state to the client. The structure definition is given later in this article. "' Godecoder: = json. Newdecoder (R.body) var RR requests. Registerrequesterr: = decoder. Decode (&RR) if err! = Nil {http. Error (W, "Invalid request Body", HTTP. statusbadrequest) Return} "Now we have a struct with request data that can be used to create a user. Therefore, the data is passed to the repository, which creates the user and returns the ID. If an error occurs at this stage, a internal server error is returned. "' goid, err: = repositories. CreateUser (JC. DB, RR. Email, RR. Name, RR. Password) If err! = Nil {log. Fatalf ("ADD User to Database error:%s", err) http. Error (W, "", http. statusinternalservererror) return} ' Finally, when the user is saved, IThey generate a random token. With a token key, the user's ID is a value that is saved to the Redis cache. Thus, user authentication can be performed in subsequent requests. "' Gotoken, err: = Crypto. Generatetoken () if err! = Nil {log. Fatalf ("Generate token Error:%s", err) http. Error (W, "", http. Statusinternalservererror) Return}onemonth: = time. Duration (60*60*24*30) * time. Seconderr = JC. Cache.set (FMT. Sprintf ("token_%s", token), StrConv. Itoa (ID), onemonth) if err! = Nil {log. Fatalf ("Add token to Redis Error:%s", err) http. Error (W, "", http. statusinternalservererror) return} ' last step, return the token to the user and set the content type to JSON format. "GOP: = map[string]string{" token ": Token,}w.header (). Set ("Content-type", "Application/json") json. Newencoder (W). Encode (P)} ' # # Last few things now, the controller and endpoint (Endpoint) are all done, but you'll notice that there are a few things missing. First, we need a request object to host the request data. ' Gotype registerrequest struct {email string ' JSON: ' email ' ' name string ' JSON: ' Name ' ' Password string ' json: ' Password ' The last step is to create a user repository. After you create the **repositories/user_repository.go** file, you need to add the **createuser** function. It will generate a random seed to sign the password and save all the data in the user table. "' Gofunc CreateUser (db *sql. DB, email, name, password string) (iNT, error) {const QUERY = ' INSERT into users (Email,name,password,salt) values ($1,$2,$3,$4) Returning ID ' Salt: = CRYPTO.G Eneratesalt () Hashedpassword: = Crypto. Hashpassword (password, salt) var id interr: = db. Queryrow (query, email, name, Hashedpassword, salt). Scan (&ID) return ID, err} "" This full cipher snippet is used throughout the article, you can be in [here] (https://github.com/rymccue/ GOLANG-STANDARD-LIB-REST-API/BLOB/MASTER/UTILS/CRYPTO/CRYPTO.GO) to find its code. In this article, it is not the core of the component, you are free to use it. # # Conclusion This controller is just a small piece of code for the API I've created to show just how easy it is to create an API with the Go language standard library. The Go language is a great language that can be used to create APIs and microservices, and perform more efficiently than other languages such as JavaScript and PHP. So, using the Go language is a very simple thing. Although only using the standard libraries to implement these, I believe that some external libraries, such as [Gorilla Mux] (Https://github.com/gorilla/mux) and [Go-validator] (https://github.com/ Go-validator/validator), makes development easier, and makes the code clearer and maintainable.

via:https://ryanmccue.ca/how-to-create-restful-api-golang-standard-library/

Author: Ryan McCue Translator: Arthurlee proofreading: polaris1119

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

609 Reads
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.