作业个人总结

作业个人总结

博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020
作业要求 https://edu.cnblogs.com/campus/zjcsxy/SE2020/homework/11633
姓名 郭浩源
学号 31801201
院系 班级 浙大城市学院计算机系 计算1803

个人任务

  1. 后端API接口
  2. 静态图片服务器配置

完成情况

后端API接口

详细接口信息在https://www.showdoc.com.cn/passtest?page_id=5863047982283518

后端接口分为以下这些,具体如何用golang实现后面再介绍

用户反馈

用户反馈这里做了两次转发,首先是向下方的请求URL发送所有数据,在这个URL对应的服务器上对图片解码,并将图片保存在此服务器上,然后向后端服务器发送对应该服务器的图片访问地址

请求URL
  • https://app.morii.top/feedback
请求方式
  • POST
参数
参数名 必选 类型 说明
openid int 用户id
feedback_type string 反馈类型
contact_info string 联系方式
feedback_content string 反馈内容
imagelist list 图片

用户注册

请求URL
  • http://api.zghy.xyz/api/user/login
请求方式
  • POST
参数
参数名 必选 类型 说明
code string wx.login获取的临时登录凭证
nickname string 昵称
gender int 性别

用户信息

请求URL
  • http://api.zghy.xyz/api/user/info
请求方式
  • POST
参数
参数名 必选 类型 说明
openid string 用户openid
birthday date 格式 2016-01-01
gender int 1:男,2:女

获得题目参数

请求URL
  • https://api.zghy.xyz/api/test/configuration
请求方式
  • POST
参数
参数名 必选 类型 说明
age_group number 0:10岁以下,1:10岁以上
test_id string 题目编号

获得题目详细内容

请求URL
  • https://api.zghy.xyz/api/test/detail
请求方式
  • POST
参数
参数名 必选 类型 说明
test_id string 题目编号
category int 表示难度或分类
num int 题目数量

提交测试成绩

请求URL
  • https://api.zghy.xyz/api/test/submit
请求方式
  • POST
参数
参数名 必选 类型 说明
openid string 用户id
age int 用户年龄
score array 用户得分
+plan_score double 计划测试得分
+attention_score double 注意测试得分
+simul_score double 同时性测试得分
+suc_score double 继时性测试得分
+total_score double 综合得分
cost_time int 测试耗时

排行榜

请求URL
  • https://api.zghy.xyz/api/test/ranklist
请求方式
  • POST
参数
参数名 必选 类型 说明
openid int 用户id
age int 用户年龄
type string P:计划,A:注意,S1:同时,S2:继时,T:综合
page_num int 查询页码
list_num int 查询记录数

历史测试

请求URL
  • http://api.zghy.xyz/api/test/gethistory
请求方式
  • POST
参数
参数名 必选 类型 说明
openid string 用户id
testyear int 测试年份
testmonth int 测试月份

查询测试详细结果

请求URL
  • https://api.zghy.xyz/api/test/getresult
请求方式
  • POST
参数
参数名 必选 类型 说明
testid int 测试编号

静态图片服务器配置

静态图片服务器在nginx中配置信息如下

端口配置在23333端口,服务器的图片存放地址通过root /root/workspace/passgo/images/来指定,可以直接通过23333端口访问来自root这个位置的图片。在后端中只需要先将图片存放到这个静态服务器上,再通过这个服务器把访问这个图片的地址存放到数据库中,这样就可以避免图片的数据直接存放在数据库中。

这里静态图片服务器写了python flask进行数据接收以及post转发。

server {
        listen       23333;
        server_name  localhost;
 
        #charset utf-8;
 
        #access_log  logs/host.access.log  main;
        
        location ~ .*\.(gif|jpg|jpeg|png)$ {  
            root /root/workspace/passgo/images/;   #指定图片存放路径  
            proxy_store on;  #启用缓存到本地的功能
            proxy_store_access user:rw group:rw all:rw;  #设置权限
            proxy_redirect          off;    
            proxy_set_header        Host 127.0.0.1;  
            proxy_set_header        X-Real-IP $remote_addr;  
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;  

            client_body_buffer_size 1280k;  #设置请求体缓冲区大小
            proxy_connect_timeout   900;  #连接超时
            proxy_send_timeout      900;  #发送超时
            proxy_read_timeout      900;  #读取超时
            proxy_buffer_size       40k;  #设置缓冲区大小,从代理后端服务器取得的第一部分的响应内容,会放到这里
            proxy_buffers           40 320k;  
            proxy_busy_buffers_size 640k;  
            proxy_temp_file_write_size 640k; 
	}
}

总结

用golang完成一个后端程序是怎样的体验

我的go程序目录如下

  • build目录是编译后的go文件,可以直接在服务器上运行(需要设置为可执行权限)
  • driver数据库连接池的建立,在程序开始的时候会调用连接池的创建
  • models通过数据库连接查询出来的数据表结构体struct
  • pkgsrc是go get 命令获取的第三方包。这里使用gin搭建web框架,go-sql-driver建立数据库连接池连接数据库。
  • gin.log存放gin的日志文件,本来是输出在终端,我将他保存在文件里了
  • goget.sh包含需要获取的第三方包内容
  • Main.gogo主程序

目录介绍完了,接下来简单介绍一下为什么要用go来完成这个后端

Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。

之前有准备继续用python flask来搭建后端,但是后来看到一篇文章,上面进行了一项高并发测试,go的速度比python快了1000倍。一个是us级,一个是ms级,没得比。当然go代码成本很高,并不像python这样的解释型语言写起来方便。go和C语言非常像,但是go的要求更加苛刻,没有被用到的变量就不能被定义,如果你定义了一个毫无用处的变量,这个程序根本无法编译。

在写go后端的时候我大概遇到了下面这几个很难受的问题

时间转换问题

数据库中对于时间有三种类型,date、datetime、timestamp。在我们这个项目中用到了date和datetime这两种类型。

首先一定要在连接数据库的地方加上parseTime=false,不然拿到的就是一个被连接池事先解析过的时间,这样的时间是无法被golang中的time库进行解析的。

golang中的时间解析也非常的奇怪time.Parse("2006-01-02 15:04:05", registerTime),他需要输入一个固定的时间,而这个时间查了以后才知道是go语言诞生的时间。

当然在我们想要把时间插入数据库的时候,直接通过time.Now()方式获取的时间是无法插入的,需要使用time.Format("2006-01-02 15:04:05")的方式将时间再转换一次,用起来比较麻烦。

json处理

看完这张图应该懂的都懂了。

当然我还是使用了官方的json库,因为试了第三方的json库,对于json数据的生成感觉不太友好(也可能只是我不太会用)

在生成json的时候,我们需要先创建一个map,map是key-value的形式,和json这样key-value的形式非常像,所以map转为json会很方便,当然也可以使用结构体。

一般我都需要先创建这样一个result map,然后通过key-value的方式加上数据。这里的interface指任何类型,这样就和json更像了。然后通过json.Marshal这个方法就可以转为一个json类型,并通过gin的web框架返回这个json给发送post的ip

result := make(map[string]interface{})
result["error_code"] = 0
mapJson, err := json.Marshal(result)
checkErr(err)
c.JSON(200, string(mapJson))

异常捕获

写过python或者java的都知道,异常捕获真香,他可以避免程序的因为这个异常而退出,只需要用类似try catch这样的语句就可以将可能报错的语句进行异常捕获。而在go中并没有这样的try catch。

在go中的异常捕获需要用panicrecover这两个方法进行实现。panic用来抛出异常,recover用来获取panic丢出的异常,并保持程序正常运行。

所以在每个post请求的回调函数中,我都需要先用defer的方式设置一个recover。比如说我们这里的用户登录,如果在接收到的post数据包中没有code这个字段的值,就可以通过panic来抛出一个异常让recover提前捕获,防止后面因为这个问题而造成其他的程序奔溃。

func recoverErr() {
	if err := recover(); err != nil {
		log.Println(err)
		fmt.Println("程序捕获,继续执行")
	}
}

func userLogin(c *gin.Context) {
	defer recoverErr()
    code := c.PostForm("code")
	if code == "" {
		result["error_code"] = 10001
		mapJson, err := json.Marshal(result)
		checkErr(err)
		c.JSON(200, string(mapJson))
		panic("code" + "字段为空")
	}
}

简单来说就是go里面的异常捕获是通过异常的提前处理来防止程序异常终止的。

目前一些基本的POST的请求都部署好了,接下来就是配合管理员的前端写一些管理员需要用到的接口了。

posted @ 2020-12-18 21:24  小y丶我又可以了  阅读(67)  评论(0编辑  收藏  举报