我的Vue之旅 09 数据数据库表的存储与获取实现 Mysql + Golang
第四期 · 将部分数据存储至Mysql,使用axios通过golang搭建的http服务器获取数据。
新建数据库
DROP DATABASE VUE;
create database if not exists vue;
use vue;
JSON TO MYSQL
JSON to MySQL (transform.tools)
DROP DATABASE VUE;
create database if not exists vue;
use vue;
CREATE TABLE gameblog (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
text VARCHAR(255),
img VARCHAR(255)
);
insert into gameblog(title,text,img) values
("Games of the Month: surrealist solitaire puzzles","What’s that? You need more games? I hear you, anonymous hapi fan.We’ve reached the part of the year when games start coming out fast","https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/11/20221102184434_1.jpg"),
("Games of the Month: Puzzles!","Sometimes you need a good puzzle game, just something to throw all of your attention at and ignore anything else going on. Well if that sometime for you is right now, then you’re in luck because in this Games of the Month","https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/11/20221102184434_2.jpg"),
("The next hapi Creator Day is July 29th!","I don’t think I’m allowed to make the entire body of this post “Thenext itch.io Creator Day is taking place on Friday July 29th.” I mean it’s true, we are hosting the next itch.io Creator Day on Friday July 29th but I should probably write more here.","https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/11/20221102184434_3.jpg");
select * from gameblog;
CREATE TABLE game (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
text VARCHAR(255),
img VARCHAR(255),
price decimal(6,2) default 0,
web boolean default 0
# TODO 发布时间
# TODO 浏览量
# TODO 评论量
# TODO 热度综合指标
);
CREATE TABLE tag (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255)
);
CREATE TABLE gametag (
gameid INT,
tagid INT
);
# TODO 外键
insert into game(id,title,text,img,price,web) values
(1,"Late Night Mop","A haunted house cleaning simulator.","https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/11/20221102193135_1.png",0,0),
(2,"an average day at the cat cafe","A haunted house cleaning simulator.","https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/11/20221102193135_2.png",0,1),
(3,"Corebreaker","A fast-paced action-platform shooter game with roguelike elements.","https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/11/20221102193135_3.png",19.99,0),
(4,"Atuel","Traverse a surrealist landscape inspired by the Atuel River in Argentina.","https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/11/20221102193135_5.png",0,0);
insert into tag values
(1,"Difficult"),
(2,"Fast-Paced");
insert into gametag values
(3,1),
(3,2),
(4,1);
DELIMITER $$
CREATE PROCEDURE gamelist()
BEGIN
# TODO
END $$
DELIMITER ;
select a.title,a.text,img,price,web,if(group_concat(c.title separator "#") is null ,"", group_concat(c.title separator "#")) as tag from game a left join gametag b on a.id = b.gameid left join tag c on b.tagid = c.id group by a.id;
本地图片上传OSS图床得到静态资源的持久地址,我使用的是PicGo图床工具。

SQL TO GOLANG STRUCT
在线sql转golang struct - 球儿工具 (qetool.com)
config.go
为了方便mysql服务器的配置,写一个配置文件。
package mysql_vue
import "database/sql"
func GetMySQLDB() (db *sql.DB, err error) {
dbDriver := "mysql"
dbUser := "root"
dbPass := "sql2008"
dbName := "vue"
db, err = sql.Open(dbDriver, dbUser+":"+dbPass+"@/"+dbName)
return
}
gameblog.go
id暂时不需要,后期路由跳转需要用到,可以先注释。
package mysql_vue
import (
"encoding/json"
_ "github.com/go-sql-driver/mysql"
)
type Gameblog struct {
// ID int64 `db:"id" json:"id"`
Title string `db:"title" json:"title"`
Text string `db:"text" json:"text"`
Img string `db:"img" json:"img"`
}
func (Gameblog) TableName() string {
return "gameblog"
}
func (Gameblog) QueryGameblog() (json_ []byte, err error) {
// db, err := sql.Open("mysql", "root:sql2008@tcp(127.0.0.1:3306)/vue")
db, err := GetMySQLDB()
checkError(err)
defer db.Close()
// ^ 必须按照顺序选取,下面的Scan需要一一对应,如果多了或少了字段会导致Scan错误.
results, err := db.Query("SELECT title,text,img FROM gameblog order by id desc")
checkError(err)
var gameBlogs []Gameblog
for results.Next() {
var gameBlog Gameblog
err = results.Scan(&gameBlog.Title, &gameBlog.Text, &gameBlog.Img)
checkError(err)
gameBlogs = append(gameBlogs, gameBlog)
}
json_, err = json.Marshal(gameBlogs)
checkError(err)
return json_, nil
}
http
Simplify server.go
前面我们把评论相关的请求处理代码写在了 server.go,移出到 comment.go,并在init初始化中绑定各个请求路径处理函数。
comment.go
package server
import (
"fmt"
"net/http"
"strconv"
)
type Comment interface {
QueryComment(pid int64) (json_ []byte, err error)
InsertComment(uid, pid int64, text string) (json_ []byte, err error)
DeleteComment(id int64) error
}
func init() {
http.HandleFunc("/insertComment", insertComment)
http.HandleFunc("/deleteComment", deleteComment)
http.HandleFunc("/queryComment", queryComment)
}
func insertComment(w http.ResponseWriter, r *http.Request) {
....
}
func deleteComment(w http.ResponseWriter, r *http.Request) {
....
}
func queryComment(w http.ResponseWriter, r *http.Request) {
....
}
gameblog.go
接口用于确保某个数据库对象实现了处理函数,否则编译不通过。
package server
import (
"fmt"
"net/http"
)
type Gameblog interface {
QueryGameblog() (json_ []byte, err error)
}
func init() {
http.HandleFunc("/queryGameblog", QueryGameblog)
}
func QueryGameblog(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
fmt.Fprintf(w, "Only GET Method")
return
}
json, err := gameblog.QueryGameblog()
if err != nil {
fmt.Fprintf(w, "Error Delete")
return
}
fmt.Fprint(w, string(json))
}
server.go
package server
import (
"log"
"net/http"
mysql_vue "wolflong.com/vue_http/lib/mysql"
sq3_vue "wolflong.com/vue_http/lib/sqlite"
)
var comment Comment = sq3_vue.Comment{}
var gameblog Gameblog = mysql_vue.Gameblog{}
func StartServer() {
err := http.ListenAndServe(":1314", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
postman test api
使用 postman 测试当前接口。

Axios
修改 HomeView.vue 的选项卡api,在 created 钩子函数添加axios请求访问。
created() {
this.axios
.get("queryGameblog")
.then((response) => {
if (!response.data) {
this.gameBlog = [];
return;
}
this.gameBlog = response.data;
})
.catch((err) => {
console.log(err);
});
},

gamelist.go
查询语句使用两次左连接,并用 group_concat 聚合函数,聚合 tag,分解tag的过程可以从服务端迁移到客户端进行降低性能消耗。
package mysql_vue
import (
"encoding/json"
"strings"
)
type Gamelist struct {
// ID int64 `db:"id" json:"id"`
Title string `db:"title" json:"title"`
Text string `db:"text" json:"text"`
Img string `db:"img" json:"img"`
Price float64 `db:"price" json:"price"`
Tag []string `db:"tag" json:"tag"` // 新添加
Web bool `db:"Web" json:"web"`
}
// type Tag struct {
// ID int64 `db:"id" json:"id"`
// Title string `db:"title" json:"title"`
// }
func (Gamelist) QueryGamelist() (json_ []byte, err error) {
db, err := GetMySQLDB()
checkError(err)
defer db.Close()
results, err := db.Query(`select a.title,a.text,img,price,web,if(group_concat(c.title separator "#") is null ,"", group_concat(c.title separator "#")) as tag from game a left join gametag b on a.id = b.gameid left join tag c on b.tagid = c.id group by a.id;`)
checkError(err)
var GameList []Gamelist
for results.Next() {
var g Gamelist
var tag string
err = results.Scan(&g.Title, &g.Text, &g.Img, &g.Price, &g.Web, &tag)
g.Tag = strings.Split(tag, "#") // 这里暂且由服务端完成分解
checkError(err)
GameList = append(GameList, g)
}
json_, err = json.Marshal(GameList)
checkError(err)
return json_, nil
}
HTTP
gamelist.go
package server
import (
"fmt"
"net/http"
)
type Gamelist interface {
QueryGamelist() (json_ []byte, err error)
}
func init() {
http.HandleFunc("/queryGamelist", QueryGamelist)
}
func QueryGamelist(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
fmt.Fprintf(w, "Only GET Method")
return
}
json, err := gamelist.QueryGamelist()
if err != nil {
fmt.Fprintf(w, "Error Delete")
return
}
fmt.Fprint(w, string(json))
}
server.go
添加语句 var gamelist Gamelist = mysql_vue.Gamelist{}

Axios
this.axios
.get("queryGamelist")
.then((response) => {
if (!response.data) {
this.latestGames.games = [];
this.mostFeatureGames.games = [];
return;
}
this.latestGames.games = response.data;
this.mostFeatureGames.games = response.data;
})
.catch((err) => {
console.log(err);
});

我的Vue之旅 09 数据数据库表的存储与获取实现 Mysql + Golang的更多相关文章
- 我的Vue之旅 10 Gin重写后端、实现页面详情页 Mysql + Golang + Gin
第三期 · 使用 Vue 3.1 + Axios + Golang + Mysql + Gin 实现页面详情页 使用 Gin 框架重写后端 Gin Web Framework (gin-gonic.c ...
- 亿级用户下的新浪微博平台架构 前端机(提供 API 接口服务),队列机(处理上行业务逻辑,主要是数据写入),存储(mc、mysql、mcq、redis 、HBase等)
https://mp.weixin.qq.com/s/f319mm6QsetwxntvSXpKxg 亿级用户下的新浪微博平台架构 炼数成金前沿推荐 2014-12-04 序言 新浪微博在2014年3月 ...
- MySQL更改数据库表的存储引擎
MySQL更改数据库表的存储引擎 1.查看表的原存储引擎 show create table user; 'user', 'CREATE TABLE `user` (\n `id` int(11) N ...
- Java获取数据库表 字段 存储的部分数据
在浏览器页面,选中图片(可多选) >单击删除按钮. 重点是, 本数据库表TabHeBeiTianQi中 存在 同一id,对应的picLocalPath字段 存储了多张图片,图片地址用 逗号 ...
- 数据库表中MAX ID获取,确保每次调用没有重复工具类(NumberUtil)
下面这个类是获取数据库中一个字段的最大值.配置在数据库中. public class NoFactory { private final static Logger cLogger = Logger. ...
- Vue刷新页面VueX中数据清空了,怎么重新获取?
Vue刷新页面VueX数据清空了,怎么重新获取? 点击打开视频讲解更详细 在vue中刷新页面后,vuex中的数据就没有了,这时我们要想使用就要重新获取数据了, 怎么在刷新后重新获取数据呢??? 这时我 ...
- mysql关于数据库表的水平拆分和垂直拆分
最初知道水平垂直分表的时候是刚参加工作不久的时候,知道了这个概念,但是公司用户量和数据量始终没上来,所以也没用到过,知道有一天到了一家新公司后,这些才被应用到实际开发中,这里我就大概说说关于水平和垂直 ...
- 用MySQL创建数据库和数据库表
1.使用SHOW语句找出在服务器上当前存在什么数据库: mysql> SHOW DATABASES; +----------+ | Database | +----------+ | mysql ...
- MySQL基于左右值编码的树形数据库表结构设计
MySQL基于左右值编码的树形数据库表结构设计 在关系型数据库中设计树形的数据结构一直是一个十分考验开发者能力的,最常用的方案有主从表方案和继承关系(parent_id)方案.主从表方案的最大缺点 ...
随机推荐
- Excel 运算符(二):比较运算符
比较运算符用于对两个数据进行比较运算,其结果为 TRUE(真)或 FALSE(假). 运算符 含义 实例 结果 = 等于 =2=3 FALSE < 小于 =5<2 FALSE > 大 ...
- 十周周末总结 MySQL的介绍与使用
python 十周周末总结 MySQL的介绍与使用 MySQL字符编码与配置文件 查看数据库的基本信息(用户,字符编码) /s windos下MySQL默认的配置文件 my_default.ini 修 ...
- [CF1539F] Strange Array (线段树)
题面 有一个长度为 n \tt n n 的序列 a \tt a a ,对于每一个位置 i ∈ [ 1 , n ] \tt i\in[1,n] i∈[1,n]: 选择一个区间 [ l , r ] \tt ...
- Python自学教程8-数据类型有哪些注意事项
不知不觉,python自学教程已经更新到第八篇了,再有几篇,基本的语法就介绍完了. 今天来总结一下数据类型有哪些需要注意的地方. 元组注意事项 元组是另一种经常使用到的数据类型,看上去和列表差不多.它 ...
- 【Java】学习路径47-线程锁synchronized
线程安全问题: 简单来说,就是多个线程在操作同一个变量时引起的问题. 这里是用一个简单的例子说明一下: 以Runnable创建的线程为例:一个售票系统,count代表当前票数,卖出一张count--. ...
- 理解 Spring IoC 容器
控制反转与大家熟知的依赖注入同理, 这是通过依赖注入对象的过程. 创建 Bean 后, 依赖的对象由控制反转容器通过构造参数 工厂方法参数或者属性注入. 创建过程相对于普通创建对象的过程是反向, 称之 ...
- 当web项目没有配置<welcome-file>index_1.jsp</welcome-file>默认标签启动tomcat后默认访问的页面是什么呢?
当web项目没有配置index_1.jsp默认标签启动tomcat后默认访问的页面是什么呢? 结果我启动后居然默认打开了index.jsp页面 为什么呢?为什么会访问我的.indexjsp页面呢?不是 ...
- 为开源提 PR
PR 可让你在 GitHub 上向他人告知你已经推送到存储库中分支的更改. 在 PR 打开后,你可以与协作者讨论并审查潜在更改,在更改合并到基本分支之前添加跟进提交. 为什么 PR 使用 PR 的主要 ...
- 从Java 9 到 Java 17 新特性梳理
Java 9 新的创建集合的方法 // [1, 2, 3, 4] List<Integer> integers = List.of(1, 2, 3, 4); // {1,2,3} ...
- Chrome 浏览器缓存的问题
浏览器缓存的问题 Chrome 在浏览器中设置: 1 Ctrl + Shift + Delete 2 Ctrl + F5 强制刷新 3 F12 打开控制台 ---> Network ---> ...