Go实战--实现简单的restful api

生命不止,继续 Go go go !!!

今天跟大家介绍一下如何使用go创建一套restful api,我们依托于开源库gorilla/mux。

let’s go~~

何为RESTful API

A RESTful API is an application program interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data.

A RESTful API – also referred to as a RESTful web service – is based on representational state transfer (REST) technology, an architectural style and approach to communications often used in web services development.

Wikipedia: 表征性状态传输(英文:Representational State Transfer,简称REST)是Roy Fielding博士于2000年在他的博士论文中提出来的一种软件架构风格。 Roy Fielding是HTTP协议(1.0版和1.1版)的主要设计者,事实上HTTP 1.1规范正是基于REST架构风格的指导原理来设计的。需要注意的是,REST是一种设计风格而不是标准,如果一个架构符合REST原则,我们就称它为RESTful架构。

gorilla/mux

github地址: https://github.com/gorilla/mux

golang自带的http.SeverMux路由实现简单,本质是一个map[string]Handler,是请求路径与该路径对应的处理函数的映射关系。实现简单功能也比较单一:

  1. 不支持正则路由, 这个是比较致命的
  2. 只支持路径匹配,不支持按照Method,header,host等信息匹配,所以也就没法实现RESTful架构

而gorilla/mux是一个强大的路由,小巧但是稳定高效,不仅可以支持正则路由还可以按照Method,header,host等信息匹配,可以从我们设定的路由表达式中提取出参数方便上层应用,而且完全兼容http.ServerMux

设置好了go的环境变量,直接运行:

go get -u github.com/gorilla/mux

实现

定义结构体,用户构造json

type Person struct {
    ID        string   `json:"id,omitemty"`
    Firstname string   `json:"firstname,omitempty"`
    Lastname  string   `json:"lastname,omitempty"`
    Address   *Address `json:"address,omitempty"`}type Address struct {
    City     string `json:"city,omitempty"`
    Province string `json:"province,omitempty"`}

接下来,定义一个全局变量,用于存储资源(数据):

var people []Person

对这个变量进行赋值:

people = append(people, Person{ID: "1", Firstname: "xi", Lastname: "dada", Address: &Address{City: "Shenyang", Province: "Liaoning"}})
people = append(people, Person{ID: "2", Firstname: "li", Lastname: "xiansheng", Address: &Address{City: "Changchun", Province: "Jinlin"}})

如果对go中的struct不够了解的可以看这里: http://blog.csdn.net/wangshubo1989/article/details/70040022

Get 获取所有person,这里我们叫people:

func GetPeople(w http.ResponseWriter, req *http.Request) {
    json.NewEncoder(w).Encode(people)
}

根据id获取person:

func GetPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)    for _, item := range people {        if item.ID == params["id"] {
            json.NewEncoder(w).Encode(item)            return
        }
    }
    json.NewEncoder(w).Encode(people)
}

然后handle function:

    router := mux.NewRouter()
    router.HandleFunc("/people", GetPeople).Methods("GET")
    router.HandleFunc("/people/{id}", GetPerson).Methods("GET")

post 同样可以,通过post操作向服务器添加数据:

func PostPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)    var person Person
    _ = json.NewDecoder(req.Body).Decode(&person)
    person.ID = params["id"]
    people = append(people, person)
    json.NewEncoder(w).Encode(people)
}

然后handle function:

router.HandleFunc("/people/{id}", PostPerson).Methods("POST")

Delete 根据id进行删除操作:

func DeletePerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)          for index, item := range people {                   if item.ID == params["id"] {
            people = append(people[:index], people[index+1:]...)                              break
        }
    }
    json.NewEncoder(w).Encode(people)
}

然后handle function:

router.HandleFunc("/people/{id}", DeletePerson).Methods("DELETE")

完整代码与运行结果

代码:

package main

import (           "encoding/json"
    "log"
    "net/http"

    "github.com/gorilla/mux")

type Person struct {
    ID        string   `json:"id,omitemty"`
    Firstname string   `json:"firstname,omitempty"`
    Lastname  string   `json:"lastname,omitempty"`
    Address   *Address `json:"address,omitempty"`
}

type Address struct {
    City     string `json:"city,omitempty"`
    Province string `json:"province,omitempty"`
}

var people []Person

func GetPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for _, item := range people {
        if item.ID == params["id"] {
            json.NewEncoder(w).Encode(item)
            return
        }
    }
    json.NewEncoder(w).Encode(people)
}

func GetPeople(w http.ResponseWriter, req *http.Request) {
    json.NewEncoder(w).Encode(people)
}

func PostPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    var person Person
    _ = json.NewDecoder(req.Body).Decode(&person)
    person.ID = params["id"]
    people = append(people, person)
    json.NewEncoder(w).Encode(people)
}

func DeletePerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for index, item := range people {
        if item.ID == params["id"] {
            people = append(people[:index], people[index+1:]...)            break
        }
    }
    json.NewEncoder(w).Encode(people)
}

func main() {
    router := mux.NewRouter()
    people = append(people, Person{ID: "1", Firstname: "xi", Lastname: "dada", Address: &Address{City: "Shenyang", Province: "Liaoning"}})
    people = append(people, Person{ID: "2", Firstname: "li", Lastname: "xiansheng", Address: &Address{City: "Changchun", Province: "Jinlin"}})
    router.HandleFunc("/people", GetPeople).Methods("GET")
    router.HandleFunc("/people/{id}", GetPerson).Methods("GET")
    router.HandleFunc("/people/{id}", PostPerson).Methods("POST")
    router.HandleFunc("/people/{id}", DeletePerson).Methods("DELETE")
    log.Fatal(http.ListenAndServe(":12345", router))
}

运行结果: Get People

package mainimport (          "fmt"
    "net/http"
    "io/ioutil")func main() {

    url := "http://localhost:12345/people"

    req, _ := http.NewRequest("GET", url, nil)

    req.Header.Add("accept", "application/json")
    req.Header.Add("authorization", "Basic d2FuZ3NodWJvOndhbmdzaHVibw==")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "18774413-0c11-e312-7ed6-7bc4f8151f5a")

    res, _ := http.DefaultClient.Do(req)          defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}

Get Person

package mainimport (          "fmt"
    "strings"
    "net/http"
    "io/ioutil")func main() {

    url := "http://localhost:12345/people/1"

    payload := strings.NewReader("{\n  \"firstname\": \"wang\",\n  \"lastname\": \"shubo\",\n  \"address\": {\n    \"city\": \"Beijing\",\n    \"state\": \"Beijng\"\n  }\n}")

    req, _ := http.NewRequest("DELETE", url, payload)

    req.Header.Add("content-type", "application/json")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "4a894ad6-2887-259a-c953-5d26fed70963")

    res, _ := http.DefaultClient.Do(req)          defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}

Post Person

package mainimport (           "fmt"
    "strings"
    "net/http"
    "io/ioutil")func main() {

    url := "http://localhost:12345/people/3"

    payload := strings.NewReader("{\n  \"firstname\": \"wang\",\n  \"lastname\": \"shubo\",\n  \"address\": {\n    \"city\": \"Beijing\",\n    \"state\": \"Beijng\"\n  }\n}")

    req, _ := http.NewRequest("POST", url, payload)

    req.Header.Add("content-type", "application/json")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "a9d590dd-1819-15f6-962e-0eabf4b7e707")

    res, _ := http.DefaultClient.Do(req)          defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}

Delete Person

package mainimport (          "fmt"
    "strings"
    "net/http"
    "io/ioutil")func main() {

    url := "http://localhost:12345/people/1"

    payload := strings.NewReader("{\n  \"firstname\": \"wang\",\n  \"lastname\": \"shubo\",\n  \"address\": {\n    \"city\": \"Beijing\",\n    \"state\": \"Beijng\"\n  }\n}")

    req, _ := http.NewRequest("DELETE", url, payload)

    req.Header.Add("content-type", "application/json")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "4c8d290e-4c6c-53f7-64e9-1d1f6ed19b09")

    res, _ := http.DefaultClient.Do(req)          defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}

原文发布于微信公众号 - 程序员的酒和故事(cppdabaojian)

原文发表时间:2017-05-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏落花落雨不落叶

canvas画简单电路图

64411
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.2K7
来自专栏芋道源码1024

熔断器 Hystrix 源码解析 —— 断路器 HystrixCircuitBreaker

本文主要基于 Hystrix 1.5.X 版本 1. 概述 2. HystrixCircuitBreaker 3. HystrixCircuitBreaker....

5377
来自专栏菩提树下的杨过

Flash/Flex学习笔记(23):运动学原理

先写一个公用的小球类Ball: package{ import flash.display.Sprite; //小球 类 public class B...

25410
来自专栏杨龙飞前端

scrollto 到指定位置

2544
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2617
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

7068
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

32210
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4878
来自专栏魂祭心

原 canvas绘制clock

4204

扫码关注云+社区