Go Web编程 Chapter7

Go web编程

Chapter_7 Creating_Web_Servies

json_creating_encoder
package main

import (
   "encoding/json"
   "fmt"
   "io"
   "os"
)

type Post struct {
   Id       int       `json:"id"`
   Content  string    `json:"content"`
   Author   Author    `json:"author"`
   Comments []Comment `json:"comments"`
}

type Author struct {
   Id   int    `json:"id"`
   Name string `json:"name"`
}

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:      1,
            Content: "Have a great day!",
            Author:  "Adam",
         },
         Comment{
            Id:      2,
            Content: "How are you today?",
            Author:  "Betty",
         },
      },
   }

   jsonFile, err := os.Create("post.json")
   if err != nil {
      fmt.Println("Error creating JSON file:", err)
      return
   }
   jsonWriter := io.Writer(jsonFile)
   encoder := json.NewEncoder(jsonWriter)
   err = encoder.Encode(&post)
   if err != nil {
      fmt.Println("Error encoding JSON to file:", err)
      return
   }
}

post.json

{"id":1,"content":"Hello World!","author":{"id":2,"name":"Sau Sheong"},"comments":[{"id":1,"content":"Have a great day!","author":"Adam"},{"id":2,"content":"How are you today?","author":"Betty"}]}
json_creating_marshal
package main

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
)

type Post struct {
   Id       int       `json:"id"`
   Content  string    `json:"content"`
   Author   Author    `json:"author"`
   Comments []Comment `json:"comments"`
}

type Author struct {
   Id   int    `json:"id"`
   Name string `json:"name"`
}

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:      1,
            Content: "Have a great day!",
            Author:  "Adam",
         },
         Comment{
            Id:      2,
            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
   }
}

post.json

{
      "id": 1,
      "content": "Hello World!",
      "author": {
            "id": 2,
            "name": "Sau Sheong"
      },
      "comments": [
            {
                  "id": 1,
                  "content": "Have a great day!",
                  "author": "Adam"
            },
            {
                  "id": 2,
                  "content": "How are you today?",
                  "author": "Betty"
            }
      ]
}
json_parsing_decoder
package main

import (
   "encoding/json"
   "fmt"
   "io"
   "os"
)

type Post struct {
   Id       int       `json:"id"`
   Content  string    `json:"content"`
   Author   Author    `json:"author"`
   Comments []Comment `json:"comments"`
}

type Author struct {
   Id   int    `json:"id"`
   Name string `json:"name"`
}

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)
   }
}

post.json

{
  "id" : 1,
  "content" : "Hello World!",
  "author" : {
    "id" : 2,
    "name" : "Sau Sheong"
  },
  "comments" : [
    { 
      "id" : 3, 
      "content" : "Have a great day!", 
      "author" : "Adam"
    },
    {
      "id" : 4, 
      "content" : "How are you today?", 
      "author" : "Betty"
    }
  ]
}
json_parsing_unmarshal
package main

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
   "os"
)

type Post struct {
   Id       int       `json:"id"`
   Content  string    `json:"content"`
   Author   Author    `json:"author"`
   Comments []Comment `json:"comments"`
}

type Author struct {
   Id   int    `json:"id"`
   Name string `json:"name"`
}

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
   }

   fmt.Println(string(jsonData))
   var post Post
   json.Unmarshal(jsonData, &post)
   fmt.Println(post.Id)
   fmt.Println(post.Content)
   fmt.Println(post.Author.Id)
   fmt.Println(post.Author.Name)
   fmt.Println(post.Comments[0].Id)
   fmt.Println(post.Comments[0].Content)
   fmt.Println(post.Comments[0].Author)

}

post.json

{
  "id" : 1,
  "content" : "Hello World!",
  "author" : {
    "id" : 2,
    "name" : "Sau Sheong"
  },
  "comments" : [
    { 
      "id" : 1, 
      "content" : "Have a great day!", 
      "author" : "Adam"
    },
    {
      "id" : 2, 
      "content" : "How are you today?", 
      "author" : "Betty"
    }
  ]
}
web_service

data.go

package main

import (
   "database/sql"
   _ "github.com/lib/pq"
)

var Db *sql.DB

// connect to the Db
func init() {
   var err error
   Db, err = sql.Open("postgres", "user=gwp dbname=gwp password=gwp sslmode=disable")
   if err != nil {
      panic(err)
   }
}

// Get a single post
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
}

// Create a new post
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
}

// Update a post
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
}

// Delete a post
func (post *Post) delete() (err error) {
   _, err = Db.Exec("delete from posts where id = $1", post.Id)
   return
}

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: ":8080",
   }
   http.HandleFunc("/post/", handleRequest)
   server.ListenAndServe()
}

// main handler function
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
   }
}

// Retrieve a post
// GET /post/1
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
}

// Create a post
// POST /post/
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
}

// Update a post
// PUT /post/1
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
}

// Delete a post
// DELETE /post/1
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
}

curl_script

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 DELETE http://127.0.0.1:8080/post/1

curl -i -X GET http://127.0.0.1:8080/post/1

curl -i -X PUT -H "Content-Type: application/json"  -d '{"content":"Updated post","author":"Sau Sheong"}' http://127.0.0.1:8080/post/1

sql

drop database gwp;
create database gwp;
drop user gwp;
create user gwp with password 'gwp';
grant all privileges on database gwp to gwp;


drop table posts;

create table posts (
  id      serial primary key,
  content text,
  author  varchar(255)
);
xml_creating_encoder
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
   }

}

post.xml

<post id="1">
   <content>Hello World!</content>
   <author id="2">Sau Sheong</author>
</post>
xml_creating_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)
   output, err := xml.MarshalIndent(&post, "", "\t\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
   }

}
<?xml version="1.0" encoding="UTF-8"?>
<post id="1">
      <content>Hello World!</content>
      <author id="2">Sau Sheong</author>
</post>
xml_parsing_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 great 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>
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 decoding 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_parsing_unmarshal_1

post.xml

<?xml version="1.0" encoding="utf-8"?>
<post id="1">
  <content>Hello World!</content>
  <author id="2">Sau Sheong</author>
</post>
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)
}
xml_parsing_unmarshal_2

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 great day!</content>
      <author>Adam</author>
    </comment>
    <comment id="2">
      <content>How are you today?</content>
      <author>Betty</author>
    </comment>
  </comments>
</post>
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"`
   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()
   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.XMLName.Local)
   fmt.Println(post.Id)
   fmt.Println(post.Content)
   fmt.Println(post.Author)
   fmt.Println(post.Xml)
   fmt.Println(post.Author.Id)
   fmt.Println(post.Author.Name)
   fmt.Println(post.Comments)
   fmt.Println(post.Comments[0].Id)
   fmt.Println(post.Comments[0].Content)
   fmt.Println(post.Comments[0].Author)
   fmt.Println(post.Comments[1].Id)
   fmt.Println(post.Comments[1].Content)
   fmt.Println(post.Comments[1].Author)
}
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy