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 条评论
登录 后参与评论

相关文章

来自专栏草根专栏

使用angular4和asp.net core 2 web api做个练习项目(二), 这部分都是angular

完成client.service.ts: import { Injectable } from '@angular/core'; import { Http, ...

4685
来自专栏我和未来有约会

Silverlight读取xml

这例子是为我的试验项目"SLShowCase"做的读取xml的试验. 项目的功能是做案例展示. ok  首先,先定义xml. projects.xml ...

1959
来自专栏Golang语言社区

Golang实现ping

ICMP部分的结构 报头 ICMP报头从IP报头的第160位开始,即第20个字节开始(除非使用了IP报头的可选部分)。 Bits 160-167 168-175...

5866
来自专栏技术博文

中小型网站服务器配置参考

入口服务器(2台): CPU:单核或双核 内存:DDR4 2G或以上 硬盘:SATA 100G或以上 网卡:千兆网卡 带宽:10Mbps独享或以上 应用服务器(...

3436
来自专栏IMWeb前端团队

如何用Node去写一个Web应用框架

第一步,用node输出一个hello world var http=require('http'); http.createServer(function(re...

2718
来自专栏Golang语言社区

golang的HTTP基本认证机制实例详解

本文实例讲述了golang的HTTP基本认证机制。分享给大家供大家参考,具体如下: 看了<<http权威指南>>第12章HTTP基本认证机制(本站下载地址:ht...

3326
来自专栏iOSDevLog

Python 刷简书的浏览量 阅读数端午节快乐。熬夜看世界杯,先刷到 10k 吧。简易爬虫 common.py

19615
来自专栏黄日成的专栏

浅析 P2P 穿越 NAT 的原理、技术、方法 ( 下 )

在 NAT 环境下,实现 P2P 通信的完整解决方案包括几个部分呢?相关的原理、方法、技术有哪些?

1.1K2
来自专栏比原链

Derek解读Bytom源码-P2P网络 upnp端口映射

Gitee地址:https://gitee.com/BytomBlockchain/bytom

683
来自专栏技术小黑屋

curl发送POST请求

curl发送POST请求 今天写Gitlab的一个merge request hook,使用curl来简化测试请求.简单备忘一下,如何使用curl发送POST请...

511

扫码关注云+社区