定义返回数据字段名
上一篇中,最后访问http://localhost:8000/users?id=1 返回结果
{"Id":1,"Username":"Lily","Password":""}
这里首写字母一般需要改为小写,修改User结构体
// 用户实体
type User struct {
// 主键
Login string `json:"login"`
// 用户登录名
Username string `json:"username"`
// 登录密码
Password string `json:"password"`
}
通过给字段添加json标签来指定实际序列化之后的字段名称;通过标签不仅可以改变字段名称,比如要忽略字段password
// 用户实体
type User struct {
// 主键
Login string `json:"login"`
// 用户登录名
Username string `json:"username"`
// 登录密码
Password string `json:"-"`
Birthday string `json:"birthday,omitempty"`
}
"-" 表示忽略字段, "omitempty" 表示忽略空值,再请求http://localhost:8000/users?id=1,返回结果
{"login":"lazy","username":"Lazy Gene","birthday":"2018-09-21"}
使用bolt保存用户
bolt是一个go语言实现的键值数据库,通过使用一个内存映射的磁盘文件来管理数据,简单易用;上一篇中临时使用map来保存用户
type UserStoreImpl struct {
// 用map 模拟存储数据库
db map[int] *domain.User
}
在应用重启后,数据自然也就丢失了,引入bolt 嵌入式数据库
go get github.com/boltdb/bolt/...
修改 iflytek.com/store/user.go
package store
import (
"iflytek.com/domain"
"log"
"github.com/boltdb/bolt"
"time"
"encoding/json"
)
func Get(login string) (*domain.User, error) {
db,err := bolt.Open("user.db", 0600, &bolt.Options{Timeout: 1 *time.Second})
if err != nil {
log.Fatal(err)
}
defer db.Close()
user := new(domain.User)
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("users"))
u := b.Get([]byte(login))
err := json.Unmarshal(u, &user)
return err
})
return user,nil
}
func Gets() ([]*domain.User,error ) {
return nil,nil
}
func Save(u *domain.User) error {
db,err := bolt.Open("user.db", 0600, &bolt.Options{Timeout: 1 *time.Second})
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.Update(func(tx *bolt.Tx) error {
// 创建一个users桶
b,err := tx.CreateBucketIfNotExists([]byte("users"))
if err != nil {
return nil
}
encoded, err := json.Marshal(u)
if err != nil {
return err
}
return b.Put([]byte(u.Login), encoded)
})
return nil
}
func Update(u *domain.User) error {
return nil
}
func Delete(id int) error {
return nil
}
看Save方法中
db,err := bolt.Open("user.db", 0600, &bolt.Options{Timeout: 1 *time.Second})
使用Open打开数据库,第一个参数为库路径,第二参数为文件模式,0600 即当前用户读写,第三个参数为配置参数,Timeout指定超时时间;再看
db.Update(func(tx *bolt.Tx) error { ...}
为写操作,这里将传入的用户对象写入到库中,在Get方法 用db.View 读取数据。
添加保存用户接口
修改 iflytek.com/main.go,添加了post方法的实现,用来保存用户
package main
import (
"iflytek.com/domain"
"iflytek.com/store"
"net/http"
"encoding/json"
"fmt"
"io/ioutil"
)
func main() {
http.HandleFunc("/users", usersHandler)
http.ListenAndServe(":8000", nil)
}
func usersHandler(w http.ResponseWriter, req *http.Request) {
if req.Method == "GET" {
id := req.URL.Query().Get("login")
if id=="" {
w.Write([]byte("未传ID参数"));
return
}
user,_ := store.Get(id)
fmt.Print(user)
b,_ := json.Marshal(user)
w.Write(b)
} else if req.Method == "POST" {
requestData,err := ioutil.ReadAll(req.Body)
if err != nil {
w.Write([]byte("{\"code\":1,\"msg\",\"解析参数失败\"}"))
}
user := new(domain.User)
json.Unmarshal(requestData, &user)
err = store.Save(user)
if err != nil {
w.Write([]byte("{\"code\":1,\"msg\",\"保存失败\"}"))
}
w.Write([]byte("{\"code\":0,\"msg\",\"OK\"}"))
}
}
完成改造!此篇优化了数据展示和引入的存储bolt, 下篇将继续对代码进行优化。