设为首页 加入收藏

TOP

Go Web:RESTful web service示例(一)
2018-12-07 14:13:31 】 浏览:89
Tags:Web RESTful web service 示例

RESTful架构的简介

web服务的架构模式主要有2种:SOAP和REST。SOAP和REST都回答了同一个问题:如何访问web服务。

SOAP风格的程序是功能驱动的,要借助xml来传递数据,明确表示要做什么动作,访问什么资源,但使用xml是非常繁琐复杂的事情。

RESTful风格的Web服务是资源驱动的,通过资源(名词)和http方法GET/POST/DELETE/PUT来实现增删改查的逻辑,偶尔也用PATCH/HEAD方法。注意,POST不是幂等的,而PUT是幂等的,所以PUT常用来更新资源,POST常用来创建资源。

关于RESTful风格的web服务,重点体现在URI上。RESTful风格的web服务的URI不能包含动词,而是只包含名词(资源)。动词或其它相关的意思可以通过http request的header/body或者通过url的query来传递。

例如:
1.获取id=1的文章:/posts/show/1,其中show是动词,这个URI就设计错了,正确的写法应该是/posts/1,然后用GET方法表示获取,即show
2.用户1转账500给2:POST /accounts/1/transfer/500/to/2,transfer是动词,是错误的,应该设计成名词,并将动词逻辑相关的参数通过URL的query或者请求报文传递

POST /transaction HTTP/1.1
Host: 127.0.0.1
  
from=1&to=2&amount=500.00

关于RESTful的web,参见阮一峰的两篇文章:

RESTful风格的web服务示例

本示例是描述如何操作博客文章的web服务,对于RESTful的规范来说,功能并不完善,但对于理解RESTful来说足够了。

两个源码文件server.go和data.go位于同个目录下,都属于main包,server.go是运行入口,data.go是数据操作逻辑的代码。

以下是server.go文件内容,定义handler。注意处理资源的方式,这是RESTful风格的web服务核心:URI中不能包含动词,只通过资源来完成动作逻辑

package main

import (
    "encoding/json"
    "net/http"
    "path"
    "strconv"
)

func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/posts/", handleRequest)
    server.ListenAndServe()
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
    var err error
    switch r.Method {
    case "GET":
        err = handleGet(w, r)
    case "POST":
        err = handlePost(w, r)
    case "PUT":
        err = handlePut(w, r)
    case "DELETE":
        err = handleDelete(w, r)
    }
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

func handleGet(w http.ResponseWriter, r *http.Request) (err error) {
    id, err := strconv.Atoi(path.Base(r.URL.Path))
    if err != nil {
        return
    }
    post, err := retrieve(id)
    if err != nil {
        return
    }
    output, err := json.MarshalIndent(&post, "", "\t\t")
    if err != nil {
        return
    }
    w.Header().Set("Content-Type", "application/json")
    w.Write(output)
    return
}

func handlePost(w http.ResponseWriter, r *http.Request) (err error) {
    len := r.ContentLength
    body := make([]byte, len)
    r.Body.Read(body)
    var post Post
    json.Unmarshal(body, &post)
    err = post.create()
    if err != nil {
        return
    }
    w.WriteHeader(200)
    return
}

func handlePut(w http.ResponseWriter, r *http.Request) (err error) {
    id, err := strconv.Atoi(path.Base(r.URL.Path))
    if err != nil {
        return
    }
    post, err := retrieve(id)
    if err != nil {
        return
    }
    len := r.ContentLength
    body := make([]byte, len)
    r.Body.Read(body)
    json.Unmarshal(body, &post)
    err = post.update()
    if err != nil {
        return
    }
    w.WriteHeader(200)
    return
}

func handleDelete(w http.ResponseWriter, r *http.Request) (err error) {
    id, err := strconv.Atoi(path.Base(r.URL.Path))
    if err != nil {
        return
    }
    post, err := retrieve(id)
    if err != nil {
        return
    }
    err = post.delete()
    if err != nil {
        return
    }
    w.WriteHeader(200)
    return
}

以下是操作数据库的data.go文件内容:

package main

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

type Post struct {
    Id      int    `json:"id"`
    Content string `json:"content"`
    Author  string `json:"author"`
}

var Db *sql.DB

func init() {
    var err error
    Db, err = sql.Open("m
编程开发网
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Golang中的三个点 下一篇Go处理json数据

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

array(4) { ["type"]=> int(8) ["message"]=> string(24) "Undefined variable: jobs" ["file"]=> string(32) "/mnt/wp/cppentry/do/bencandy.php" ["line"]=> int(214) }