更多Go内容请见: https://blog.youkuaiyun.com/weixin_39777626/article/details/85066750
Web服务
定义:与其他软件程序进行交互的软件程序
注意:终端用户不是人类而是软件程序
前后台通信方式
SOAP | REST | |
---|---|---|
全称 | Simple Object Access Protocal(简单对象访问协议) | Representational State Transfer(具体状态传输) |
实质 | 一种协议 | 一种设计理念 |
功能 | 用于交换定义在XML里面的结构化数据,能够跨越不同的网络协议并在不同的编程模型中使用 | 用于设计那些通过标准的几个动作来操纵资源,并以此来进行相互交流的程序 |
区别 | 功能驱动 | 数据驱动 |
关注点 | API的设计 | 被发送报文的格式 |
使用的数据类型 | XML | JSON |
注意:在REST只允许用户使用指定的几个HTTP方法操纵资源,不允许用户对资源执行任意的动作,为此要发送特殊请求时,可以使用以下方法:
- 将动作转换为资源
- 将动作转换为资源的属性
如:要发送以下请求时可以这么做
ACTIVATE /user/456 HTTP/1.1
way1:
POST /user/456/activation HTTP/1.1
{“date”:“2015-05-15T13:05:05z”}
way2:
PATCH /user/456 HTTP/1.1
{"active":"true"}
通过Go分析和创建XML
分析XML
步骤:
- 创建用于存储XML数据的结构
- 使用xml.Unmarshal将XML数据解封到结构里面
post.xml
<?xml version="1.0" encoding="utf-8"?>
<post id="1">
<content>Hello World!</content>
<author id="2">Sau Sheong</author>
</post>
xml.go
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
Xml string `xml:",innerxml"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
func main() {
xmlFile, err := os.Open("post.xml")
if err != nil {
fmt.Println("Error opening XML file:", err)
return
}
defer xmlFile.Close()
xmlData, err := ioutil.ReadAll(xmlFile)
if err != nil {
fmt.Println("Error reading XML data:", err)
return
}
var post Post
xml.Unmarshal(xmlData, &post)
fmt.Println(post)
}
使用Decoder
post.xml
<?xml version="1.0" encoding="utf-8"?>
<post id="1">
<content>Hello World!</content>
<author id="2">Sau Sheong</author>
<comments>
<comment id="1">
<content>Have a good day!</content>
<author id="3">Adam</author>
</comment>
<comment id="2">
<content>How are you today?</content>
<author id="4">Betty</author>
</comment>
</comments>
</post>
xml.go
package main
import (
"encoding/xml"
"fmt"
"io"
"os"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
Xml string `xml:",innerxml"`
Comments []Comment `xml:"comments>comment"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
type Comment struct {
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
func main() {
xmlFile, err := os.Open("post.xml")
if err != nil {
fmt.Println("Error opening XML file:", err)
return
}
defer xmlFile.Close()
decoder := xml.NewDecoder(xmlFile)
for {
t, err := decoder.Token()
if err == io.EOF {
break
}
if err != nil {
fmt.Println("Error decodeing XML into tokens:", err)
return
}
switch se := t.(type) {
case xml.StartElement:
if se.Name.Local == "comment" {
var comment Comment
decoder.DecodeElement(&comment, &se)
fmt.Println(comment)
}
}
}
}
创建XML
使用Marshal函数
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
func main() {
post := Post{
Id: "1",
Content: "Hello World!",
Author: Author{
Id: "2",
Name: "Sau Sheong",
},
}
output, err := xml.Marshal(&post)
if err != nil {
fmt.Println("Error marshalling to XML:", err)
return
}
err = ioutil.WriteFile("post.xml", output, 0644)
if err != nil {
fmt.Println("Error writing XML to file:", err)
return
}
}
生成的post.xml文件
<post id="1"><content>Hello World!</content><author id="2">Sau Sheong</author></post>
使用MarshalIndent函数
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
func main() {
post := Post{
Id: "1",
Content: "Hello World!",
Author: Author{
Id: "2",
Name: "Sau Sheong",
},
}
output, err := xml.MarshalIndent(&post, "", "\t")
if err != nil {
fmt.Println("Error marshalling to XML:", err)
return
}
err = ioutil.WriteFile("post.xml", []byte(xml.Header+string(output)), 0644)
if err != nil {
fmt.Println("Error writing XML to file:", err)
return
}
}
生成的post.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<post id="1">
<content>Hello World!</content>
<author id="2">Sau Sheong</author>
</post>
手动将Go结构编码至XML
过程:
- 1.创建结构&填充数据
- 2.创建XML文件(存储XML数据)
- 3.创建编码器(编码结构)
- 4.编码器将结构编码至XML文件
代码
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
func main() {
post := Post{
Id: "1",
Content: "Hello World!",
Author: Author{
Id: "2",
Name: "Sau Sheong",
},
}
xmlFile, err := os.Create("post.xml")
if err != nil {
fmt.Println("Error creating XML file:", err)
return
}
encoder := xml.NewEncoder(xmlFile)
encoder.Indent("", "\t")
err = encoder.Encode(&post)
if err != nil {
fmt.Println("Error encoding XML to file:", err)
return
}
}
通过Go分析和创建JSON
分析JSON
post.json
{
"id":1,
"content":"Hello World!",
"author":{
"id":2,
"name":"Sau Sheong"
},
"comments":[
{
"id":3,
"content":"Have a good day!",
"author":"Adam"
},
{
"id":4,
"content":"How are you today?",
"author":"Betty"
}
]
}
JSON分析程序
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type Post struct {
Id int `json:"id,attr"`
Content string `json:"content"`
Author Author `json:"author"`
Comments []Comment `json:"comments"`
}
type Author struct {
Id int `json:"id,attr"`
Name string `json:",chardata"`
}
type Comment struct {
Id int `json:"id"`
Content string `json:"content"`
Author string `json:"author"`
}
func main() {
jsonFile, err := os.Open("post.json")
if err != nil {
fmt.Println("Error opening JSON file:", err)
return
}
defer jsonFile.Close()
jsonData, err := ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println("Error reading JSON data:", err)
return
}
var post Post
json.Unmarshal(jsonData, &post)
fmt.Println(post)
}
使用Decoder
package main
import (
"encoding/json"
"fmt"
"io"
"os"
)
type Post struct {
Id int `json:"id,attr"`
Content string `json:"content"`
Author Author `json:"author"`
Comments []Comment `json:"comments"`
}
type Author struct {
Id int `json:"id,attr"`
Name string `json:",chardata"`
}
type Comment struct {
Id int `json:"id"`
Content string `json:"content"`
Author string `json:"author"`
}
func main() {
jsonFile, err := os.Open("post.json")
if err != nil {
fmt.Println("Error opening JSON file:", err)
return
}
defer jsonFile.Close()
decoder := json.NewDecoder(jsonFile)
for {
var post Post
err := decoder.Decode(&post)
if err == io.EOF {
break
}
if err != nil {
fmt.Println("Error decoding Json:", err)
return
}
fmt.Println(post)
}
}
创建JSON
将结构封装为JSON
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
type Post struct {
Id int `json:"id,attr"`
Content string `json:"content"`
Author Author `json:"author"`
Comments []Comment `json:"comments"`
}
type Author struct {
Id int `json:"id,attr"`
Name string `json:",chardata"`
}
type Comment struct {
Id int `json:"id"`
Content string `json:"content"`
Author string `json:"author"`
}
func main() {
post := Post{
Id: 1,
Content: "Hello World!",
Author: Author{
Id: 2,
Name: "Sau Sheong",
},
Comments: []Comment{
Comment{
Id: 3,
Content: "Have a great day!",
Author: "Adam",
},
Comment{
Id: 4,
Content: "How are you today?",
Author: "Betty",
},
},
}
output, err := json.MarshalIndent(&post, "", "\t\t")
if err != nil {
fmt.Println("Error marshalling to JSON:", err)
return
}
err = ioutil.WriteFile("post.json", output, 0644)
if err != nil {
fmt.Println("Error writing JSON to File:", err)
return
}
}
使用Encoder
package main
import (
"encoding/json"
"fmt"
"os"
)
type Post struct {
Id int `json:"id,attr"`
Content string `json:"content"`
Author Author `json:"author"`
Comments []Comment `json:"comments"`
}
type Author struct {
Id int `json:"id,attr"`
Name string `json:",chardata"`
}
type Comment struct {
Id int `json:"id"`
Content string `json:"content"`
Author string `json:"author"`
}
func main() {
post := Post{
Id: 1,
Content: "Hello World!",
Author: Author{
Id: 2,
Name: "Sau Sheong",
},
Comments: []Comment{
Comment{
Id: 3,
Content: "Have a great day!",
Author: "Adam",
},
Comment{
Id: 4,
Content: "How are you today?",
Author: "Betty",
},
},
}
jsonFile, err := os.Create("post.json")
if err != nil {
fmt.Println("Error creating JSON file:", err)
return
}
encoder := json.NewEncoder(jsonFile)
err = encoder.Encode(&post)
if err != nil {
fmt.Println("Error encoding JSON to file:", err)
return
}
}
创建Go Web服务
server,go
package main
import (
"encoding/json"
"net/http"
"path"
"strconv"
)
type Post struct {
Id int `json:"id"`
Content string `json:"content"`
Author string `json:"author"`
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/post/", 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/lib/pq"
)
var Db *sql.DB
func init() {
var err error
Db, err = sql.Open("postgres", "user=postgres dbname=testdb password=*********** sslmode=disable")
if err != nil {
panic(err)
}
}
func retrieve(id int) (post Post, err error) {
post = Post{}
err = Db.QueryRow("select id,content,author from posts where id=$1", id).Scan(&post.Id, &post.Content, &post.Author)
return
}
func (post *Post) create() (err error) {
statement := "insert into posts (content,author) values ($1,$2) returning id"
stmt, err := Db.Prepare(statement)
if err != nil {
return
}
defer stmt.Close()
err = stmt.QueryRow(post.Content, post.Author).Scan(&post.Id)
return
}
func (post *Post) update() (err error) {
_, err = Db.Exec("update posts set content=$2,author=$3 where id=$1", post.Id, post.Content, post.Author)
return
}
func (post *Post) delete() (err error) {
_, err = Db.Exec("delete from posts where id=$1", post.Id)
return
}
创建
curl -i -X POST -H "Content-Type:application/json" -d '{"content":"My first post","author":"Sau Sheong"}' http://127.0.0.1:8080/post/
获取
curl -i -X GET http://127.0.0.1.:8080/post/1
更新
curl -i -X PUT -H "Content-Type:application/json" -d '{"content":"Updated psot","author":"Sau Sheong"}' http://127.0.0.1:8080/post/1
删除
curl -i -X DELETE http://127.0.0.1:8080/post/1
更多Go内容请见: https://blog.youkuaiyun.com/weixin_39777626/article/details/85066750