Self-hacking marathon-creating a Web service based on the go language from scratch

Source: Internet
Author: User
Tags install go
This is a creation in Article, where the information may have evolved or changed.

What can I do in 20 hours? Maybe the muddle is over, maybe you can read some books, do some work, read several blogs, write a one or two blog, and so on. The hackathon (HackAthon) is a self-challenge-to see what you can do in a limited short period of time. For example, a person without a language experience would use that language to implement 4 of the following RESTful APIs (assuming the language is go).

* language Go* Frame Random * Back-end Database Redis or SQLite, only need one can # # API list * post/location* get/location* get/location/{name}* delete/location/{name}### Post/location adds support for the city if it already exists in the database, returns 409, otherwise returns 201 Example 1 post/location{"name": "Shanghai"}201 created example 2post/location{" Name ":" Shanghai "}201 createdpost/location{" name ":" Shanghai "}409 conflicted### get/location returns all cities in the database example 3 Get/loca tion200 ok[] Example 4post/location{"name": "Shanghai"}201 createdpost/location{"name": "Beijing"}201 Createdget/location2 XX ok["Shanghai", "Beijing"]### Get/location/{name} Query openweathermap.com, return results, because the weather data updates infrequently, can be slowed in the database, reserved for 1 hours do not need to consider a query openweathermap.com return error Case example 5get/location/ Shanghai200 ok{"Weather": [{"description": "Few Clouds", "icon": "02d", "id" : 801, "main": "Clouds"}]}### Delete/location/{name} example 6delete/location/shanghai200 OK 


According to the above description, to invoke the Openweathermap.com Web site's restful API, the specific way to invoke the following:
Curl "Api.openweathermap.org/data/2.5/weather?q=shanghai&appid=xxxxxxxxxxxxxxxxxxxxxxxxxx" {"coord": {"Lon" : 121.46, "lat": 31.22}, "Weather": [{"id": 801, "main": "Clouds", "description": "Few Clouds", "icon": "02d"}], "base": "CMC Stations "," main ": {" temp ": 286.15," pressure ": 1019," humidity ":" Temp_min ": 286.15," Temp_max ": 286.15}," Wind ": {" Speed ": 7," deg ":" $ "," clouds ": {" All ": $}," DT ": 1458608400," sys ": {" type ": 1," id ": 7452," message ": 0.0091," Country ":" CN "," Sunrise ": 1458597323," Sunset ": 1458641219}," id ": 1796236," name ":" Shanghai "," cod ": 200}## parameter * Q: City name * APPID: Xxxxxxxxxxxxxxxxxxxxxxxxxx is a pre-applied ID

All of the above, is the subject of the hacker marathon requirements.

What do you do for a person who has no go language experience?

Well, although there is no go experience, but can not understand anything. There is still some experience in developing restful APIs, even in Python and Java. But the framework used in the past is never applied to go. Does go have a framework for Web service? Check, there is really, there is a very well-known framework called Beego, or a Chinese major development, even the documents have Chinese version, it is really a lot of things saved.

That being so, before using the framework, always learn the go language. And you always have to install go before you learn the go language. I am very embarrassed that the author recently did not have a good Linux machine, had to be installed on Windows. After installation, the environment variables Goroot and GOPATH are configured as described in the native documentation, and the%goroot%/bin and%gopath%/bin are added to the%path% system environment variables; then look at the document, get a general idea of the file directory structure of Go and some commands, It's still very useful. For example, the go Get Command borrows (Chao) (xi) Apt-get or pip install, can download libraries from GitHub, and automatically resolves all dependencies and auto build. This is still a great thing.

It's a bit slow to look at the native document, so hurry up and take a look at some simple tutorials. The author found 3 relatively good concise tutorials as follows:

http://www.vaikan.com/go/a-tour-of-go/
Http://coolshell.cn/articles/8460.html
Http://coolshell.cn/articles/8489.html

Well, after spending 2.5 hours learning the basics of go, I actually found out that the original Go native library "Net/http" comes with a Web server, see this document "Wrting Web Applications":

https://golang.org/doc/articles/wiki/

Well, the basic skills are almost there, now it should be possible to try the Beego framework. Where do you start? Of course, start with the document first. Through the documentation, we have learned that we can create a basic Web service and a restful API-based Web service with the Bee New command and the Bee API command, respectively. Aha, found, Bee API, that's what I want. But wait, at least install the frame first. Then, depending on the documentation, you should execute the following command:

Go get Github.com/astaxie/beegogo get Github.com/beego/bee
The first command is used to install the Beego library, which is the framework. The second command is used to install the Beego toolset, which is the Bee New command and Bee API commands.
OK, the framework of the basic environment set up, just write a small example of it. This is the most basic step of self-learning. For this study, run the Bee API <project_name> command. In this way, a new project will be built successfully. Go into the code and you'll see that this sample project implements the API for object and user. Then, run the following command to build:

Go Install github.com/<project_name>
After the build is complete, run the following command in the project directory to let the Web server in project Run!

Bee Run
Then, with postman try to get a few, such as: Get Http://localhost:8080/object really have JSON return! That's great! A Web service is running up!

What should I do next? Yes, that's the way to change someone else's sample! Into the 4 api! we need to achieve. Haha, it seems to be close to success, isn't it? Ah, what's missing?

That's right! What is the database used in the background? Carefully read the sample code in the model package implementation, there is no database! Well, let's write it myself. with Which? According to the requirements of the topic, only Redis or sqlite3, and then according to Beego documents, Beego only support Mysql,postgresql and sqlite3. OK, so there is no choice, only with Sqlite3. It's just a database that I didn't use again. However, I have seen others used! Although not written code, but finally know that this thing is not difficult to use, is a lightweight file database.

According to the previous experience with Cassandra and Elasticsearch, Sqlite3 must have the go language driver. Continue to Beego documents and sqlite3 documents and know to run the following command to install Sqlite3 's go language driver.

Go get github.com/mattn/go-sqlite3
Well, the driver is ready. Let's just put this database in the bag. After the installation, only to find that this is really lightweight ah. Directly on a single directory, there are sqlite3.exe,sqlite3.dll and so few files. Simply add the directory to%path% and you can use it directly. It's simple. Indeed a few years ago to see a chess AI program is the use of SQLite to do the opening library. So, in the command line tried a few sqlite3, feel pretty cool.

Ok! All the previous work has been completed, start it!!

Or look at the code. The RESTful API project generated by Beego is an MVC architecture.

1. In Main.go the main is to load some necessary libraries, and then the HTTP server run up;

2. Inside the router.go, the routing is set. This should be familiar to flask, Django and other frameworks.

3. Inside the controllers package, the controller is set, that is, the first layer after the router.

4. Specific to the database dealing with, nature is still in the models package inside. This part of the code is the hardest to write. First of all, the original sample program does not have, secondly, to use the Beego ORM module to do, but also to learn the ORM module things.

The author Chi Chi, tossing has 10 hours, finally galloped, even the document with Bing (write code this place son Google was wall, tried a few VPN are bad), finally to toss out.

The specific code is pasted as follows:

1. Main.go

Package Mainimport (    _ "Github.com/cityweather/docs"    _ "Github.com/cityweather/routers" _ "    github.com/ Mattn/go-sqlite3 "        " Time "    " Github.com/astaxie/beego "    " Github.com/astaxie/beego/orm ") func init () {    ORM. RegisterDatabase ("Default", "Sqlite3", "./weather.db")    ORM. RUNSYNCDB ("Default", False, True)    orm. Defaulttimeloc = time. Utc}func Main () {    beego. Run ()}

2. Router.go

Package Routersimport (    "github.com/cityweather/controllers"    "Github.com/astaxie/beego") func init () {    Beego. Router ("/location/?:name", &controllers. cityweathercontroller{})}

3. Controller_cityweather.go

Package Controllersimport ("Encoding/json" "Github.com/cityweather/models" "Github.com/astaxie/beego")//Ope Rations about Cityweathertype cityweathercontroller struct {beego. controller}//@router/location [post]//Body: {"name": "Somecity"}//Return: "201 Created" or "409 conflicted" func (o *ci Tyweathercontroller) Post () {var cn models. CityName JSON. Unmarshal (O.ctx.input.requestbody, &AMP;CN) Responsecode: = models. Addonecity (&AMP;CN) o.ctx.output.status = responsecode}//@router/location/?:name [Get]func (o *CityWeatherControl ler) Get () {Name: = O.ctx.input.param (": Name") if name! = "" {CW, err: = models. Getonecity (name) if err! = Nil {o.data["json"] = Err. Error ()} else {o.data["json"] = CW}} else {//name is empty and then Get all cities ' name S cities: = models. Getallcities () o.data["json"] = cities} o.servejson ()}//@router/location/:name [delete]//returN:always OK func (o *cityweathercontroller) Delete () {Name: = O.ctx.input.param (": Name") models.    Delete (name) o.data["JSON"] = "Delete success!" O.servejson ()}

4. Model_cityweather.go

Package Modelsimport ("FMT" "Time" "Net/http" "Io/ioutil" "Github.com/astaxie/beego/orm" "github.co M/bitly/go-simplejson "_" Github.com/mattn/go-sqlite3 ") const weathertable string =" City_weather "Const Timeoutset I Nt64 = 3600const Openweatherurl string = "Http://api.openweathermap.org/data/2.5/weather" Const AppID string = "                         Xxxxxxxxxxxxxxxxxxxxxxxx "type cityname struct {Name string}type cityweather struct {Id int Primary key, auto increment Name string ' orm: ' Unique; '                      '//city name Summary string//Main in weather Description string                         Description in Weather icon string//icon in weather Wid int ID in Weather TimeStamp Int64//TimeStamp when Updating}func init () {orm. Registermodel (New (Cityweather))}func Addonecity (CN *cityname) (Responsecode int) {cw: = new (Cityweather) CW. Name = CN. Name CW. Wid =-1 cw. TimeStamp = 0 FMT. PRINTLN (CW) o: = orm. Neworm () o.using ("main") _, Err: = O.insert (CW) Responsecode = 201 If Err! = Nil {if Err.            Error () = = "UNIQUE constraint failed:city_weather.name" {responsecode = 409//conflicted} else {    Responsecode = $//server Error}} return Responsecode}func getallcities () []string { Allcities: = []string{}//dynamic array o: = orm. Neworm () o.using ("main") Qs: = o.querytable (weathertable) var lists []orm. Paramslist num, err: = Qs. Valueslist (&lists, "name") if Err = = Nil {fmt. Printf ("Result Nums:%d\n", num) for _, Row: = Range Lists {fmt. Println (row[0]) allcities = append (Allcities, row[0]. ( String)}} return Allcities}func getonecity (city string) (CW Cityweather, err error) {o: = orm. Neworm() o.using ("main") Qs: = o.querytable (weathertable) Err = qs. Filter ("name", city). One (&AMP;CW) if err! = Nil {cw = Cityweather{id:-1} return CW, err} currenttime: = time. Now (). UTC (). Unixnano () DiffSeconds: = (CURRENTTIME-CW. TimeStamp)/1e9 FMT. Printf ("Diff seconds =%d\n", diffseconds) if diffseconds > Timeoutset | | cw. Wid = =-1 {//older than one hour or the first get, then need to update database client: = &http. client{} URL: = Openweatherurl + "? q=" + City + "&appid=" + APPID reqest, err: = http. Newrequest ("GET", url, nil) if err! = Nil {panic (err) fmt. Println ("Error happened when calling Openweather")} response, Resperr: = client. Do (reqest) defer response. Body.close () if resperr! = nil {fmt.            Printf ("Response Error:%s\n", Resperr)} else {//Get Response from openweather!! Body, err: = Ioutil. ReadAll (response. Body) If err! = Nil {panic (err. Error ())} js, err: = Simplejson. Newjson (body) if err! = Nil {panic (err. Error ()} weather, OK: = js. Checkget ("Weather") if OK {fmt. PRINTLN (Weather) desc, _: = weather. GetIndex (0). Get ("description"). String () icon, _: = weather. GetIndex (0). Get ("icon"). String () ID, _: = weather. GetIndex (0). Get ("id"). Int () Wtr, _: = weather. GetIndex (0). Get ("main"). String () num, err: = Qs. Filter ("name", city). Update (ORM.                    params{"description": Desc, "Summary": WTR,//"main" field                "WID": ID, "icon": Icon, "Time_stamp": CurrentTime,}) Fmt. Printf ("num =%d\n", num) if Err! = Nil {fmt. PRINTLN (ERR) Panic (err)} err = qs. Filter ("name", city).                    One (&AMP;CW)//Get CW after updating if err! = Nil {cw = Cityweather{id:-1}    Return CW, Err}}}} return CW, Err}func Delete (city string) { o: = orm. Neworm () o.using ("main") Qs: = o.querytable (weathertable) num, err: = Qs. Filter ("name", city). Delete () If Err = = Nil {fmt. PRINTLN (num)} else {fmt. Println ("Error happened in Delete () ...")}}

All right, finish the call! Tonight's bridal chamber is no problem! A puff of blood was sprayed out ...

What can I do for 20 hours? 20 hours can be from a golang illiterate to the above this hacker marathon basically run out.
No matter the future is bright or dark, I believe that I must be able to deal with more and stronger challenges!

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.