go入门项目:(3) Bookstore-REST-API
介绍
书店 REST API
这是基于 REST 的 API,用于列出、添加、更新和删除书籍。因为是入门项目,所以不会有第 3 方包、身份验证和数据库。
本文来自博客园,作者:Jayvee,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/bookstore-rest-api.html
CRUD API
- Get all the books - http://localhost:8080
- Get book by id - http://localhost:8080/book?id=1
- Delete book by id - http://localhost:8080/delete?id=5
- Add books - http://localhost:8080/add
- Update book - http://localhost:8080/update
添加书籍示例
[
{
"id": "4",
"title": "Rust权威指南",
"price": "49.90"
}
]
更新书籍示例
{
"id": "4",
"title": "Rust权威指南进阶",
"price": "149.90"
}
本文来自博客园,作者:Jayvee,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/bookstore-rest-api.html
代码实现
main.go
点击查看代码
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
// struct based on books.json file. Please refer
type Book struct {
Id string `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
Price string `json:"price"`
Imageurl string `json:"image_url"`
}
// define port
const PORT string = ":8080"
// message to send as json response
type Message struct {
Msg string
}
// response as json format
func jsonMessageByte(msg string) []byte {
errrMessage := Message{msg}
byteContent, _ := json.Marshal(errrMessage)
return byteContent
}
// print logs in console
func checkError(err error) {
if err != nil {
log.Printf("Error - %v", err)
}
}
// main function starts here
func main() {
// http://localhost:8080
http.HandleFunc("/", handleGetBooks)
// http://localhost:8080/book?id=1
http.HandleFunc("/book", handleGetBookById)
// http://localhost:8080/add
http.HandleFunc("/add", handleAddBook)
// http://localhost:8080/update
http.HandleFunc("/update", handleUpdateBook)
// http://localhost:8080/delete?id=1
http.HandleFunc("/delete", handleDeleteBookById)
fmt.Printf("App is listening on %v\n", PORT)
err := http.ListenAndServe(PORT, nil)
// stop the app is any error to start the server
if err != nil {
log.Fatal(err)
}
}
// List all the books handler
func handleGetBooks(w http.ResponseWriter, r *http.Request) {
books, err := getBooks()
// send server error as response
if err != nil {
log.Printf("Server Error %v\n", err)
w.WriteHeader(500)
w.Write(jsonMessageByte("Internal server error"))
} else {
booksByte, _ := json.Marshal(books)
w.Write(booksByte)
}
}
// get book by id handler
func handleGetBookById(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
// get book id from URL
bookId := query.Get("id")
book, _, err := getBookById(bookId)
// send server error as response
if err != nil {
log.Printf("Server Error %v\n", err)
w.WriteHeader(500)
w.Write(jsonMessageByte("Internal server error"))
} else {
// check requested book exists or not
if (Book{}) == book {
w.Write(jsonMessageByte("Book Not found"))
} else {
bookByte, _ := json.Marshal(book)
w.Write(bookByte)
}
}
}
// add book handler
func handleAddBook(w http.ResponseWriter, r *http.Request) {
// check for post method
if r.Method != "POST" {
w.WriteHeader(405)
w.Write(jsonMessageByte(r.Method + " - Method not allowed"))
} else {
// read the body
newBookByte, err := ioutil.ReadAll(r.Body)
// check for valid data from client
if err != nil {
log.Printf("Client Error %v\n", err)
w.WriteHeader(400)
w.Write(jsonMessageByte("Bad Request"))
} else {
books, _ := getBooks() // get all books
var newBooks []Book // to add new book
json.Unmarshal(newBookByte, &newBooks) // new book added
books = append(books, newBooks...) // add both
// Write all the books in books.json file
err = saveBooks(books)
// send server error as response
if err != nil {
log.Printf("Server Error %v\n", err)
w.WriteHeader(500)
w.Write(jsonMessageByte("Internal server error"))
} else {
w.Write(jsonMessageByte("New book added successfully"))
}
}
}
}
// update book handler
func handleUpdateBook(w http.ResponseWriter, r *http.Request) {
// check for post method
if r.Method != "POST" {
w.WriteHeader(405)
w.Write(jsonMessageByte(r.Method + " - Method not allowed"))
} else {
// read the body
updateBookByte, err := ioutil.ReadAll(r.Body)
// check for valid data from client
if err != nil {
log.Printf("Client Error %v\n", err)
w.WriteHeader(400)
w.Write(jsonMessageByte("Bad Request"))
} else {
var updateBook Book // to update a book
err = json.Unmarshal(updateBookByte, &updateBook) // new book added
checkError(err)
id := updateBook.Id
book, _, _ := getBookById(id)
// check requested book exists or not
if (Book{}) == book {
w.Write(jsonMessageByte("Book Not found"))
} else {
books, _ := getBooks()
for i, book := range books {
if book.Id == updateBook.Id {
books[i] = updateBook
}
}
// write books in books.json
err = saveBooks(books)
// send server error as response
if err != nil {
log.Printf("Server Error %v\n", err)
w.WriteHeader(500)
w.Write(jsonMessageByte("Internal server error"))
} else {
w.Write(jsonMessageByte("Book updated successfully"))
}
}
}
}
}
// delete book by id handler
func handleDeleteBookById(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
// get book id from URL
bookId := query.Get("id")
book, book_index, err := getBookById(bookId)
// send server error as response
if err != nil {
log.Printf("Server Error %v\n", err)
w.WriteHeader(500)
w.Write(jsonMessageByte("Internal server error"))
} else {
// check requested book exists or not
if (Book{}) == book {
w.Write(jsonMessageByte("Book Not found"))
} else {
books, _ := getBooks()
// remove books from slice
books = append(books[:book_index], books[book_index+1:]...)
saveBooks(books)
w.Write(jsonMessageByte("Book deleted successfully"))
}
}
}
books.go
点击查看代码
package main
import (
"encoding/json"
"io/ioutil"
)
// Get books - returns books and error
func getBooks() ([]Book, error) {
books := []Book{}
booksByte, err := ioutil.ReadFile("./books.json")
if err != nil {
return nil, err
}
err = json.Unmarshal(booksByte, &books)
if err != nil {
return nil, err
}
return books, nil
}
// Get books - returns book, book index and error
func getBookById(id string) (Book, int, error) {
books, err := getBooks()
var requestedBook Book
var requestedBookIndex int
if err != nil {
return Book{}, 0, err
}
for i, book := range books {
if book.Id == id {
requestedBook = book
requestedBookIndex = i
}
}
return requestedBook, requestedBookIndex, nil
}
// save books to books.json file
func saveBooks(books []Book) error {
// converting into bytes for writing into a file
booksBytes, err := json.Marshal(books)
checkError(err)
err = ioutil.WriteFile("./books.json", booksBytes, 0644)
return err
}
运行
根目录下 go build,然后执行文件。
本文来自博客园,作者:micromatrix,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/bookstore-rest-api.html

浙公网安备 33010602011771号