个人blog系统 前后端分离 前端js后端go

系统设计:

1.使用语言:前端使用vue,并使用axios向后端发送数据。后端使用的是go的gin框架,并使用grom连接数据库实现数据存储读取。

2.设计结构:

最终展示:仅展示添加模块,其他模块基本相似

前端部分

基础的页面设计部分使用的是flex布局,这里就不过多的讲解了。

由于vue是模块化的,所以这个页面可以分为三大模块

1.就是app.vue这个是最主要的,我们的页面是通过它来显示的

2.就是左侧的导航栏,它对应四个模块,根据选择模块不同来显示不同的页面

3.就是右侧的交互部分,四个交互页面对应四个导航栏的选项

运行端口

运行端口有默认的端口,如果需要自定义端口。我们需要在项目文件中找到vue.config.js文件。然后在里面设置:

javascript 复制代码
原来的文件内容:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
 
})


修改后
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer:{//主要添加这个
    port: 3000,
    open: true,
  }
})

port指定端口,open指定程序运行的时候是否自动打开浏览器true为打开

组件

想要使用组件就需要提前加载组件,也就是导入它(import ...)

加载之后才能挂载(router-view)

我们首先要明确的目标是:1 加载 2对应的组件 2 加载 3对应的组件

我们一步一步来看

大致的文件结构如下图所示,仅做展示,为了方便了解结构

app.vue:

html 复制代码
<template>
<div class="father">
  <div class="one">
    <h1>blog control center</h1>
  </div>
  <div>
    <index />
  </div>
</div>
</template>

<script>
import index from "./views/index.vue"


export default {
  name: "App",
  components: {
    index,
  }
}
</script>

<style>

.father {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
.one{
  width: 1380px;
  height: 100px;
  background: #8e96f1;
  text-align: center;
  display: flex;
  justify-content: center;
}

</style>

App.vue这是整个项目的根组件。其他所有的组件都是基于这个组件展开的

我们主要在这个组件内做了:

  1. 加载 index组件
  2. 制作了HTML的头部区域,也就是显示blog control center 的部分
  3. 规定了index的显示区域(为头部区域下方
  4. 给body设置了一个flex布局,让网页内容居中显示

加载组件就是在组件的script部分通过import导入,加载分为全局加载和组件内加载

在上面的代码中我们使用的是组件内加载,它的特点是,在其组件内加载的组件只能在此组件内使用。而全局加载的特点是只要我们使用全局加载,那么在这个项目内所有组件都可以使用我们加载的组件。

全局加载步骤:首先在main.js里面加载需要用的组件。

import xxx from "相对路径" xxx就相当于我们给这个组件起的别名

然后我们会看到一个语句:const app = createApp(APP)

然后通过 app.conponent("组件名",组件名)

注意:如果没有找到const app = createApp(APP)那就是被集成为了createApp(APP).use(router).mount('#app')放在最下方。这时候我们需要把它拆开

我们来看一个简单的例子:

复制代码
import index from  "./views/index.vue"

const app =createApp(App)

app.component("index",index)

app.use(router).mount('#app')

这就是全局导入的基本步骤了。在这里导入之后就不需要在组件内搞import和components了。直接<index />就可以使用了

这里我们就讲解完了,接下来我们来看index的设置

index:

html 复制代码
<template>
<div class="body">
  <div >
    <div class="son" style="background-color: #42b983">
      <router-link to="/add" ><h1>添加博文</h1></router-link>
    </div>
    <div class="son" style="background-color: gold">
      <router-link to="/change"><h1>修改博文</h1></router-link>
    </div>
    <div class="son" style="background-color: pink">
      <router-link to="/discover"> <h1>查询博文</h1></router-link>
    </div>
    <div class="son" style="background-color: coral">
      <router-link to="/del"> <h1>删除博文</h1></router-link>
    </div>
  </div>
  <div style="width: 1200px;height: 1120px;">
<router-view></router-view>
  </div>
</div>
</template>

<script>

export default {
  setup() {
    return{
    }
  },

}
</script>

<style scoped>

.son{
  width: 180px;
  height: 280px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.body{
  display: flex;
  flex-direction: row;
}
</style>

这里主要要理解的是router-view和router-link

router-view是组件要挂载到哪里的入口,也就是说我的router-view放在div里面,我的子组件展示的时候就只能在这个div里面展示。它起到一个占位符的作用,需要与router-link结合使用

router-link就相当于一个连接,这个连接里面设置的路径是我们在router目录里面提前设置好的。针对于这个项目我们来看一下router里面index.js的设置

html 复制代码
import { createRouter, createWebHashHistory } from 'vue-router'
import index from "../views/index.vue"
import add from "../views/add.vue"
import change from "../views/change.vue"
import discover from "../views/discover.vue"
import del from "../views/del.vue"


const routes = [
  {
    path: '/index',
    component: index,
  }
  ,{
  path: '/add',
    component: add,

  }
  ,{
  path: '/change',
    component: change,
  }
  ,{
  path: '/discover',
    component: discover,
  }
  ,{
  path: '/del',
    component: del,
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

路径的设置主要是创建一个数组,数组存储对象,对象存储路径信息(path和component)path是我们设置的路径,component是我们导入的组件。由于它是一个.js文件不知道哪些组件被注册为全局组件。所以需要重新加载一次

最后我们再创建一个router,吧createRouter([])赋值给它。在这个函数里面有两个参数。这里暂且略过,因为博主也没有很理解这个。就暂且按照博主的写法来吧(嘻嘻)

最后的export default router这个语句的作用是导出一个router对象。这样问再main里面才可以使用(app.use(router))(注:使用之前需要import导入index.js所在的相对地址哦)

到此,router-view和router-link我们也大致的明白是怎么回事了,简单来说就是router-link连接显示的组件会显示到router-view里面。

然后我们再来看四个不同模块文件

add.vue:

html 复制代码
<script>
import {ref} from "vue";
import axios from "axios"
export default{
  name:"add",
  setup(props,context) {
    let name = ref("")
    let text = ref("")
    let rese =ref("")
    function give(e) {
      e.preventDefault()
      axios.post("http://localhost:8081/Add",{
        name: name.value,
        text: text.value
      }).then(res => {
        console.log(res)
        alert(res.data.Error)
        rese.value = res.data.Error
      })
    }
    return{
      give,
      name,
      text,
    }
  }

}
</script>

<template>
 <div class="rit">
   <form method="post"  @submit="give" >
   <table>
     <tr class="a"><td> 请输入博文名称: <input name="name" v-model="name" type="text" style="width: 500px"><input  type="submit" value="提交" class="submit-button"></td></tr>
     <tr class="b"><td><textarea name="text" v-model="text" /></td></tr>
   </table>
   </form>
 </div>
</template>

<style scoped>
div{
  display: flex;
  align-items: center;
  justify-content: center;
}
.rit{
  width: 1200px;
  height: 1120px;
  background: #42b882;
}
.a{
width:1200px;
  height: 100px;
}
.b{
  width:1200px;
  height: 1025px;
}
textarea{
  width:1100px;
  height:1000px;
  overflow:auto;
}
</style>
全局css样式

这里我们不怎么酱它的css样式,只简单了解一下:通常来说,组件之间的css样式不会互相影响,也就是说我在哪个组件设置的样式就只能用在哪个组件内。

如果有一个样式会被运用到很多组件内,我们就可以设置全局css样式

全局css样式

设置全局css样式我们需要单独写一个css文件,通常这个文件我们会存放在src/assets目录下。

导入全局组件同样需要在main.js里面导入(import "css样式路径(相对路径)")

这样就可以直接在组件内使用这个文件内的样式了。

axios 传递数据

这里我们传递数据使用到了axios作为传递的工具。

我们首先导入这个axios,同样的。既然是导入就会有全局导入和组件内导入

组件内导入很简单,我们不过多赘述

我们主要来讲一下全局导入

在main.js我们首先 import axios from "axios"导入

然后

axios.defaults.baseURL = 'http://localhost:8081'; // 设置默认的 baseURL

这里设置的作用是在组件内使用的时候就不需要写完整的路径了,只需要补出后面剩余路径即可:.post("http://localhost:8081/Add" 就可以写为.post("/Add"

这样就会方便很多。

然后app.config.globalProperties.axios = axios; 这一句的作用类似于起别名。我们在组件内导入的时候使用axios直接使用就可以了。但是全局导入就需要this.axios了 axios也可以改成别的名字,这个看自己需要。也可以不写,但是我们通常会写上哦

如果使用全局导入,我们刚才的代码就需要改为:

javascript 复制代码
 setup(props,context) {
    let name = ref("")
    let text = ref("")
    let rese =ref("")
    function give(e) {
      e.preventDefault()
      this.$axios.post("/Add",{
        name: name.value,
        text: text.value
      }).then(res => {
        console.log(res)
        alert(res.data.Error)
        rese.value = res.data.Error
      })
    }

this.$axios

这里要着重声明的是,在vue3的里面这个方法就不是很适用了。因为setup没有自己的this

我们需要

复制代码
import {getCurrentInstance} from "vue";事先导入这个
复制代码
const { proxy } = getCurrentInstance(); // 然后再在setup里面创建这个常量。通过

proxy.$axios进行使用,这里的差异要注意

我们使用this.$axios.post.("url",{json键值对数据})向后端发送请求。然后再.then(res=>{接收回应})接收后端返回的回应(一般都是res.data里面有回应的数据)。然后再.catch捕获错误信息,这个在本系统内并没有使用(不会)

ref变量

这个是vue3里面新出的一个,通过它来创建响应式变量,用于绑定页面内元素。实现动态的变化。如果要在js所属的代码部分访问它的值是不能直接用变量名的,而是需要使用 变量名.value 获取变量的值。

v-model绑定

它的主要作用是把一个变量绑定到某个元素上,这个变量要是响应式变量。它有一个语法糖,就是先读取后渲染。把它综合到了v-model里面。

change.vue:

javascript 复制代码
<script>
import { ref } from "vue";

export default {
  name: "add",
  setup() {
    let change_text = ref("");
    let Blog_body = ref("");
    let Blog_title = ref("");

    function change_submit(e) {
      e.preventDefault();
      console.log("change_text:", change_text.value); // 检查值
      this.$axios.post("/Change",{
        "Title": change_text.value
      }).then((response) => {
        console.log(response);
        Blog_body.value = response.data.Blog_body;
        Blog_title.value = response.data.Blog_title;
        alert("i get the blog");
      });
    }
    function change_out(e){
      e.preventDefault()
      alert("数据发送回后端",Blog_title,Blog_body)
      this.$axios.post("/Changeend", {
        BlogText: Blog_body.value,
        BlogName:Blog_title.value,
      }).then((response) => {
        alert(response.data.return);
      })
    }

    return {
      change_submit,
      change_text,
      Blog_title,
      Blog_body,
      change_out,
    };
  },
};
</script>

<template>
  <div class="rit">
    <form method="post" @submit="change_submit">
      <table>
        <tr class="a">
          <td>
            请输入要修改的博文的名称:<input type="text" style="width: 500px" v-model="change_text" />
            <input type="submit" value="提交" class="submit-button" />
          </td>
        </tr>

      </table>
    </form>
    <form @submit="change_out" id="f2">
      <table>
        <tr class="a">
          <td>
            blog_name:<input type="text" style="width: 500px" v-model="Blog_title" />
            <input type="submit" value="确认提交" class="submit-button">
          </td>
        </tr>
        <tr class="b">
          <td>
            <textarea v-model="Blog_body"></textarea>
          </td>
        </tr>
      </table>
    </form>
  </div>
</template>

<style scoped>
div{
  display: flex;
  align-items: center;
  justify-content: center;
}
.rit{
  width: 1200px;
  height: 1120px;
  background: #fdd600;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.a{
  width:1200px;
  height: 50px;
  text-align: center;
}
.b{
  width:1200px;
  height: 1025px;
}
textarea{
  width:1100px;
  height:1000px;
  overflow:auto;
}
</style>

这个里面就没有什么特别新的内容了,我们简单理解一下设计概念即可。在change模块中。主要步骤如下

  1. 前端输入blog的name
  2. 发送给后端,后端返还blog的name和内容 这是第一次前后端交流
  3. 用户修改,再次返回给后端
  4. 后端接收,修改数据库中的数据(是修改不是新建一个新的数据)这是第二次前后端交流

这里着重讲一下的是使用了两个路由,一个路由用于第一次前后端交流,另一个路由用于第二次前后端交流。

其他的部分都是之前讲过的了。就不过多赘述了

后面的del.vue和discover.vue模块都是重复的内容,我们只把代码贴出来,剩下的就略过了

del.vue

javascript 复制代码
<script>
import {ref} from "vue";


export default{
  name:"add",
  setup() {
    let blogs_name = ref("")
    function del_blog(e){
      e.preventDefault()
      console.log("函数被触发")
      this.$axios.post("/Delete",
          {"blog_name":blogs_name.value}).then(res=>{
        alert("blog 删除"+res.data.return)
        console.log(res)
      })

    }
    return {
      blogs_name,
      del_blog,
    }
  }

}
</script>

<template>
  <div class="rit">
    <form method="post" @submit="del_blog" >
      <table>
        <tr class="a"><td> 请输入要删除的博文名称: <input type="text" style="width: 500px" v-model="blogs_name"><input type="submit" value="提交" class="submit-button" ></td></tr>
      </table>
    </form>
  </div>
</template>

<style scoped>
div{
  display: flex;
  align-items: center;
  justify-content: center;
}
.rit{
  width: 1200px;
  height: 1120px;
  background: #fd7e50;
}
.a{
  width:1200px;
  height: 100px;
}

textarea{
  width:1100px;
  height:1000px;
  overflow:auto;
}
</style>

discover.vue

javascript 复制代码
<script>
import {ref} from "vue";


export default{
  name:"add",
  setup() {
    let change_text = ref("");
    let Blog_body = ref("");
    let Blog_title = ref("");

    function change_submit(e) {
      e.preventDefault();
      console.log("change_text:", change_text.value); // 检查值
      this.$axios.post("/Discover",{
        "Title": change_text.value
      }).then((response) => {
        console.log(response);
        Blog_body.value = response.data.Blog_body;
        alert("i get the blog");
      });
    }

    return {
      Blog_body,
      Blog_title,
      change_text,
      change_submit,
    }
  }

}
</script>

<template>
  <div class="rit">
    <form method="post" @submit="change_submit">
      <table>
        <tr class="a"><td> 请输入要查询的博文名称: <input type="text" style="width: 500px" v-model="change_text"><input type="submit" value="提交"  class="submit-button"> </td></tr>
        <tr class="b"><td><textarea v-model="Blog_body"/></td></tr>
      </table>
    </form>
  </div>
</template>

<style scoped>
div{
  display: flex;
  align-items: center;
  justify-content: center;
}
.rit{
  width: 1200px;
  height: 1120px;
  background: #fdbfca;
}
.a{
  width:1200px;
  height: 100px;
}
.b{
  width:1200px;
  height: 1025px;
}
textarea{
  width:1100px;
  height:1000px;
  overflow:auto;
}
</style>

路由设置

路由的设置我们一般都在router/index.js文件内设置。这个目录我们可以手动创建,也可以在项目创建的时候直接选定创建。

跟随项目一起创建:

这里有一个Router选项,勾选上就可以。

手动创建:

我们创建对应目录以及文件,这个时候是不能使用的。我们还需要在main.js里面设置

复制代码
import router from './router'
复制代码
app.use(router)

设置完这两个就说明我们启用了路由系统。

具体路由的设置我们在index:对应的部分已经理解过了。这里就简单赘述一下

路由的设置是设置一个数组,数组存放对象们,对象里面包含两个参数,一个是path,另一个是component,path设置的是路径,compoent设置的是路径对应跳转哪个界面。

如果有嵌套路径的存在,就需要再在改对象里面添加一个属性

复制代码
children: [
    
]

这个里面存放的数据和外部的是一样的,path,component如果还有嵌套内容就再写一个children。并且嵌套的路径不需要再写 斜杠/ 直接写路径就可以了,这个斜杠会自动补充。

前端部分大概就讲这一点吧。更加深层的还是需要看更权威的专家的讲解或者去看官方文档。

后端部分

后端我们使用的是go语言的gin框架

大致的架构我们讲一下

主要是分为三个模块,一个是路由模块,一个是路由对应处理函数模块,一个是与数据库的连接模块。

我们首先来讲一下最重要的路由模块(其实都很重要)

main.go:

这个文件主要负责路由的设置。

Go 复制代码
package main

import (
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)


// 同一目录下,同一包内的.go文件内函数是共享的
func main() {
	router := gin.Default()
	router.Use(cors.Default())
	router.POST("/Add", Addpost)         //
	router.POST("/Change", Change)       //这是前端查询并返回查询结果的路径
	router.POST("/Changeend", Changeend) //这是后端接收前端处理好的结果的路径
	router.POST("./Discover", Discover)
	router.POST("/Delete", Delete)
	router.Run(":8081") //运行指定端口
}

我们既然要使用gin框架就需要实现导入这个框架。也就是:import "github.com/gin-gonic/gin"

,然后我们就可以设置路由了,这里需要注意设置的路由需要和前端对应上,而且要严格区分大小写!!!我们先通过router:= gin.Default()创建了一个默认的gin路由引擎。

然后我们设置了很多条路由,通过 .请求方法("路由",对应的处理函数)

最后使用router.Run(":8081")运行。

这里提到了端口,我们前端运行的时候也是需要端口的。双方端口不能一样,如果一样会导致端口占用错误,但是端口不一样虽然不会导致错误出现。却引发了一个新的问题:跨域

跨域问题的解决在前端后端都可以,但是我们还是默认在后端解决跨域问题。

router.Use(cors.Default())这条语句就是解决跨域问题的,它在"github.com/gin-contrib/cors"包下,所以要事先导入这个包。但是这部分博主并不是很精通,就不讲了。只能说通过router.Use(cors.Default())语句我们可以设置一些默认的设定解决跨域问题。

然后就是路由后面跟着的处理函数,这个函数我们是写在与main.go同级目录下并且都属于包main。所以可以直接使用不用导入对应的包。

至于为什么函数不加()是因为如果加了()就是直接使用这个函数。这并不是我们需要的。我们需要的是在特定情况下跳转到对应的处理函数。所以没有加上()

mysql.go:

Go 复制代码
package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type blog struct {
	BlogName string `gorm:"primaryKey type:varchar(255)"`
	BlogText string `gorm:"not null unique type:text"`
} //创建一个结构体,结构体用于存储博文和博文名称

func sqlof() *gorm.DB { //这是一个数据库连接函数,当我们调用它的时候会返回一个数据库对象。我们用这个对象进行数据的增上改查
	dsn := "root:123456@tcp(127.0.0.1:3306)/web_of_blog"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
	}
	db.AutoMigrate(&blog{})

	return db
}

这个文件的主要作用是连接数据库并提供一个函数,函数返回一个数据库对象。

我们需要创建一个结构体对象,这个对象的字段和数据库里面的字段一一对应。

dsn是一个字符串,字符串的内容是用户:密码@协议(ip,端口)/数据库名称

ip使用的是127.0.0.1是说明这是本机的数据库。

我们使用gorm.Open(mysql.Open(dsn),&gorm.Config{})连接数据库,它会返会一个对象和错误信息。如果连接成功是没有错误信息的,即err==nil

db.AutoMigrate(&blog{})的作用是确认数据库里有对应的表(结构体名称+s)如果没有则自动创建,如果表的结构不同则更新结构。

我们把最后的连接好的对象作为返回值返回给调用者。

controller.go

这个部分可以说是后端的灵魂所在了

Go 复制代码
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

var ch = make(chan string, 1)
var db = sqlof()      //创建数据库全局对象
type Article struct { //这个结构体用于接收前端数据博文和博文名称
	Name string `json:"name"`
	Text string `json:"text"`
}
type change_blog_title struct {
	Title string `json:"title"`
}

func Addpost(c *gin.Context) {
	var article Article
	if err := c.ShouldBindJSON(&article); err != nil {
		c.JSON(400, gin.H{"error": "解析 JSON 失败"})
		return
	}

	var insert blog //创建一个结构体对象,用于存储从前端读取的数据
	insert.BlogName = article.Name
	insert.BlogText = article.Text
	if db.Create(&insert).Error != nil { //判断数据库插入操作是否成功,成功返回200不成功返回500
		c.JSON(500, gin.H{
			"Error": "error",
		})
		/*这里返回的是json数据格式,所以前端读取的时候就需要使用.Error读取对应的key值*/
	} else {
		c.JSON(200, gin.H{
			"Error": "no error",
		})
	}
}

// Change /*前端发送一个title作为博文的名字给后端,后端读取这个数据然后查询,并返回查询结果*/
func Change(c *gin.Context) {

	fmt.Println("change函数被成功调用,说明后端路由设置无误")
	var title change_blog_title //这是一个博文的表头的结构体实例对象
	var content blog
	//通过前端发送的数据来把title赋值给后端的title然后再通过db对象进行查询,并把查询结果的信息返回给后端
	err := c.ShouldBindJSON(&title)
	if err != nil {
		fmt.Println("error")
	}
	fmt.Println("jianche", title.Title)
	ch <- title.Title

	db.Table("blogs").Where("blog_name = ?", title.Title).First(&content) //把查询到的第一个结果返回给content进行数据绑定
	c.JSON(200, gin.H{                                                    //返回查询到的文章和数据
		"Blog_body":  content.BlogText,
		"Blog_title": content.BlogName,
	})
	fmt.Println("数据已返回", content.BlogName, content.BlogText)

}
func Changeend(c *gin.Context) { //接收数据并修改,然后返回修改完成还是错误
	blog_name := <-ch
	date := blog{}
	if err := c.ShouldBindJSON(&date); err != nil {
		c.JSON(400, gin.H{
			"return": "数据写入错误",
		})
	}
	result := db.Table("blogs").Where("blog_name = ?", blog_name).Update("blog_text", date.BlogText)
	if result.Error != nil {
		c.JSON(500, gin.H{"return": "更新博文失败"})
		return
	}
	result = db.Table("blogs").Where("blog_name = ?", blog_name).Update("blog_name", date.BlogName)
	if result.Error != nil {
		c.JSON(500, gin.H{"return": "更新博文失败"})
		return
	} else {
		c.JSON(200, gin.H{
			"return": "修改成功",
		})
	}

}

func Discover(c *gin.Context) {
	fmt.Println("discover函数被成功调用,说明后端路由设置无误")
	var title change_blog_title //这是一个博文的表头的结构体实例对象
	var content blog
	//通过前端发送的数据来把title赋值给后端的title然后再通过db对象进行查询,并把查询结果的信息返回给后端
	err := c.ShouldBindJSON(&title)
	if err != nil {
		fmt.Println("error")
	}
	fmt.Println("jianche", title.Title)

	db.Table("blogs").Where("blog_name = ?", title.Title).First(&content) //把查询到的第一个结果返回给content进行数据绑定
	c.JSON(200, gin.H{                                                    //返回查询到的文章和数据
		"Blog_body": content.BlogText,
	})
	fmt.Println("数据已返回", content.BlogName, content.BlogText)

}

type DeleteRequest struct {
	BlogName string `json:"blog_name"`
}

func Delete(c *gin.Context) {
	var request DeleteRequest
	err := c.ShouldBindJSON(&request)
	if err != nil {
		c.JSON(400, gin.H{
			"return": "出现错误,啦啦啦",
		})
		return
	}

	blog_name := request.BlogName
	fmt.Println("i get it: ", blog_name)

	resout := db.Where("blog_name = ?", blog_name).Delete(&blog{})
	if resout.Error != nil {
		c.JSON(500, gin.H{
			"return": "error",
		})
	} else {
		c.JSON(200, gin.H{
			"return": "ok",
		})
	}
}

它根据不同路由的设置来执行对应的函数,这一整个文件的核心就是c *gin.Context这个

c *gin.Context 是 Gin 框架中处理 HTTP 请求的核心对象,它的主要作用包括:

  • 获取请求信息:如请求头、请求体、查询参数、路径参数等。

  • 生成响应:如返回 JSON、HTML、文本等。

  • 管理中间件:在请求处理过程中传递数据。

  • 控制流程:如中止请求、重定向等。

我们通过它获取前端发送的数据,并且返回给前端数据。

我们使用c.ShouldBindJSON(&结构体)把数据绑定到结构体,这需要我们提前创建一个空的结构体对象。对象的字段名称要与前端通过axios传递过来的json数据的key值相同

也就是我前端传递数据{"Name":"123","age":18}后端的结构体字段就需要是Name和age默认的类型都是string字符串类型。同样的,前端获取后端的回应也是如此。只不过我们前端使用的是

.then(res=>{

我们需要使用res.data.返回json数据的key获取对应的value

})

绑定完成之后我们就获取到了前端发送的请求了。

然后就是与数据库交互的部分了,这部分我们之前在gorm讲过

使用gorm连接数据库

至于为什么后端没有用mvc架构,是因为代码量不大,而且模块也就三个用不上架构。

相关推荐
梦想CAD控件3 分钟前
在线CAD开发包结构与功能说明
前端·javascript·vue.js
张拭心8 分钟前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
时光不负努力8 分钟前
typescript常用的dom 元素类型
前端·typescript
小怪点点14 分钟前
大文件切片上传
前端
时光不负努力14 分钟前
TS 常用工具类型
前端·javascript·typescript
SuperEugene16 分钟前
Vue状态管理扫盲篇:Vuex 到 Pinia | 为什么大家都在迁移?核心用法对比
前端·vue.js·面试
张拭心18 分钟前
Android 17 来了!新特性介绍与适配建议
android·前端
徐小夕23 分钟前
pxcharts-vue:一款专为 Vue3 打造的开源多维表格解决方案
前端·vue.js·github
Hilaku23 分钟前
我会如何考核一个在简历里大谈 AI 提效的高级前端?
前端·javascript·面试
进击的尘埃36 分钟前
Vue3 中 emit 能 await 吗?事件机制里的异步陷阱
javascript