ch7/ch7-07 #154
ch7/ch7-07
#154
Replies: 5 comments 2 replies
-
Practice 7.11还是有很多优化没做, 比如文件打开失败直接panic, 改为报错就好了, 但是我懒的改了~_~ 写的不好,大神轻喷~~~ package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"os/signal"
"strconv"
)
// 增加额外的handler让客户端可以创建,读取,更新和删除数据库记录。
// 例如,一个形如 /update?item=socks&price=6
// 的请求会更新库存清单里一个货品的价格并且当这个货品不存在或价格无效时返回一个错误值。
//(注意:这个修改会引入变量同时更新的问题)
// TODO:
// 1. 将数据保存到本地json文件
// 2. 开启web服务时读取本地json文件
// 3. 读取数据时,如果本地json文件不存在,则从默认值获取数据
// 4. 实现web服务器
// 5. 实现增删改查
// 6. 关闭服务器时保存数据到本地json文件
type dollars float32
func (d dollars) String() string {
return fmt.Sprintf("$%.2f", d)
}
type database map[string]dollars
// list 货物清单
func (db database) list(w http.ResponseWriter, req *http.Request) {
for item, price := range db {
fmt.Fprintf(w, "%s: %s\n", item, price)
}
}
// price 价格
func (db database) price(w http.ResponseWriter, req *http.Request) {
item := req.URL.Query().Get("item")
price, ok := db[item]
if !ok {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, "no such item: %q\n", item)
return
}
fmt.Fprintf(w, "%s\n", price)
}
// create 创建
func (db database) create(w http.ResponseWriter, req *http.Request) {
item := req.URL.Query().Get("item")
price := req.URL.Query().Get("price")
_, ok := db[item]
if ok {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, "item 已经存在: %q\n", item)
return
}
// string to float
priceF, err := strconv.ParseFloat(price, 32)
if err != nil {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, "price is invalid: %q\n", price)
return
}
db[item] = dollars(priceF)
fmt.Fprintf(w, "create item: %q\n", item)
fmt.Fprintf(os.Stdout, "item create: %q\n", db)
}
// update 更新
func (db database) update(w http.ResponseWriter, req *http.Request) {
item := req.URL.Query().Get("item")
price := req.URL.Query().Get("price")
_, ok := db[item]
if !ok {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, "item 不存在: %q\n", item)
return
}
// string to float
priceF, err := strconv.ParseFloat(price, 32)
if err != nil {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, "price is invalid: %q\n", price)
return
}
db[item] = dollars(priceF)
fmt.Fprintf(w, "update item: %q\n", item)
fmt.Fprintf(os.Stdout, "item update: %q\n", db)
}
// delete 删除
func (db database) delete(w http.ResponseWriter, req *http.Request) {
item := req.URL.Query().Get("item")
_, ok := db[item]
if !ok {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, "item 不存在: %q\n", item)
return
}
delete(db, item)
fmt.Fprintf(w, "delete item: %q\n", item)
fmt.Fprintf(os.Stdout, "item delete: %q\n", db)
}
// 默认数据
var defaultDB database = database{"shoes": 50, "socks": 5}
// 数据库
var db database
func loadDB() error {
path := "/Users/dugulingping/code/Golang/Study/src/study/day9Interface/Practice/db.json"
// 打开文件
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
return err
}
// 关闭文件
defer file.Close()
// 读取文件, 解析json文件
decoder := json.NewDecoder(file)
if err := decoder.Decode(&db); err != nil {
// 如果文件为空,则从默认值获取数据
if err == io.EOF {
// 从默认值获取数据
fmt.Fprintln(os.Stdout, "从默认值获取数据")
db = defaultDB
return nil
} else {
// 如果文件不为空,但是解析失败,则返回错误
return err
}
}
return nil
}
// saveDB 保存数据到本地json文件
func saveDB() {
path := "/Users/dugulingping/code/Golang/Study/src/study/day9Interface/Practice/db.json"
// 打开文件
file, err := os.OpenFile(path, os.O_RDWR, 0755)
if err != nil {
panic(err)
}
// 关闭文件
defer file.Close()
// 清空文件
file.Truncate(0)
// 从头开始写入
file.Seek(0, 0)
// 编码json文件
encoder := json.NewEncoder(file)
if err := encoder.Encode(db); err != nil {
panic(err)
}
fmt.Fprintf(os.Stdout, "save db: %q", db)
}
func main() {
// 从本地json文件读取数据
err := loadDB()
if err != nil {
fmt.Fprintf(os.Stdout, "loadDB err: %q", err)
}
// 创建通道
c := make(chan os.Signal)
// 监听指定信号 ctrl+c kill
signal.Notify(c, os.Interrupt)
// 启动一个协程
// 目的是当接收到指定信号时,执行保存数据库
go func() {
select {
case sig := <-c:
fmt.Printf("Got %s signal. Aborting...\n", sig)
// 保存数据库
saveDB()
// 退出程序
os.Exit(1)
}
}()
// 创建路由
http.HandleFunc("/list", db.list)
http.HandleFunc("/price", db.price)
http.HandleFunc("/create", db.create)
http.HandleFunc("/update", db.update)
http.HandleFunc("/delete", db.delete)
// 监听端口
http.ListenAndServe("localhost:8000", nil)
} emmmmm, 练习7.12感觉是重复的习题, 上一节就有模版表格的应用, 我就不做了 |
Beta Was this translation helpful? Give feedback.
0 replies
-
先他吗的过一遍吧,说点啥,真是不知道 |
Beta Was this translation helpful? Give feedback.
2 replies
-
抱歉了,打扰到大佬了~B站里逛习惯了,感谢大佬翻译,我会控制下自己,把理解到的东西和补充发在评论区,再次感谢大佬回复,对于之前的评论深表歉意,您可以把没用的删掉
| |
zhangbest5
|
|
***@***.***
|
---- Replied Message ----
| From | ***@***.***> |
| Date | 1/13/2023 14:40 |
| To | ***@***.***> |
| Cc | ***@***.***> ,
***@***.***> |
| Subject | Re: [gopl-zh/gopl-zh.github.com] ch7/ch7-07 (Discussion #154) |
这本书其实适用于有其他后端编程语言(如 c++, java, Python, Php, Rust)的基础的人去阅读, 无任何其他后端编程语言经验的人, 还是去 B 站看看视频吧, 推荐老郭的视频. 请不要在评论区输出这些"看不懂啊, 什么什么的"其实毫无意义, 有问题请直接提出问题. 比如哪里看不懂? 并贴出具体的代码, 如果有,请一并提供报错信息.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Beta Was this translation helpful? Give feedback.
0 replies
-
7.12
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
ch7/ch7-07
中文版
https://golang-china.github.io/gopl-zh/ch7/ch7-07.html
Beta Was this translation helpful? Give feedback.
All reactions