go原生http开发简易blog(一)项目简介与搭建
文章目录
- 一、项目简介
- 二、项目搭建前置知识
- 三、首页- - -前端文件与后端结构体定义
- 四、配置文件加载
- 五、构造假数据- - -显示首页内容
代码地址:https://gitee.com/lymgoforIT/goblog
一、项目简介
使用Go
原生http
开发一个简易的博客系统,包含一下功能:
- 文章增删改查,文章列表分页显示
- 评论系统
- 文章分类、归档
学习本项目能学到什么?
- 使用Go开发web项目基本思路,初步具有工程思维,如路由分组、目录组织,代码封装等。
- 博客基本功能开发套路,如博客与评论的查询、分类、归档、分页等。
循序渐进,掌握编程思维和思路
。这一点是最重要的,会不断优化代码,而不是一步给出最终代码,这样更能培养编程思维和思路。
页面效果
二、项目搭建前置知识
接下来,我们会一步一步实现博客首页,开始我们可能会把代码都写到main.go
中,后期再不断调整,优化,形成工程化的目录结构。
首先是启动一个http
服务的代码,如下:
package mainimport ("log""net/http"
)func main(){server := http.Server{Addr: "127.0.0.1:8080",}http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {writer.Write([]byte("ok"))})if err := server.ListenAndServe();err != nil {log.Println(err)}
}
启动后,浏览器访问,可以看到ok
字样
这里返回给前端的不过是一个字符串而已,实际工作中一般前后端交互都是使用的JSON
数据或者protoc
协议的,那么想要返回JSON
字符串给前端,又该如何做呢?
其实也简单,设置好请求头即可,如下:
package mainimport ("encoding/json""log""net/http"
)type IndexData struct {Title string `json:"title"`Desc string `json:"desc"`
}func index(w http.ResponseWriter, r *http.Request) {// 设置请求头,指明返回的是JSON数据w.Header().Set("Content-Type", "application/json")var indexData IndexDataindexData.Title = "go博客"indexData.Desc = "入门学习笔记"jsonStr, _ := json.Marshal(indexData)w.Write(jsonStr)
}func main() {server := http.Server{Addr: "127.0.0.1:8080",}http.HandleFunc("/", index)if err := server.ListenAndServe(); err != nil {log.Println(err)}
}
目前浏览器得到的响应结果都是后端直接返回的数据,但我们前端是给用户使用的,需要有一定页面才行。
在Go
中渲染html
页面,可以使用Go
自带的html/template
库,使用方式如下:
首先建立template/index.html
文件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
hello lym blog!!
<br>
标题:{{.Title}}
<br>
描述:{{.Desc}}
</body>
</html>
package mainimport ("encoding/json""fmt""html/template""log""net/http""os"
)type IndexData struct {Title string `json:"title"`Desc string `json:"desc"`
}func index(w http.ResponseWriter, r *http.Request) {// 设置请求头,指明返回的是JSON数据w.Header().Set("Content-Type", "application/json")var indexData IndexDataindexData.Title = "go博客"indexData.Desc = "入门学习笔记"jsonStr, _ := json.Marshal(indexData)w.Write(jsonStr)
}func indexHtml(w http.ResponseWriter, r *http.Request) {// 使用给定的名字分配一个html模板t := template.New("index.html")viewPath, _ := os.Getwd()// 将html文件关联到模板上t, _ = t.ParseFiles(viewPath + "/template/index.html")var indexData IndexDataindexData.Title = "go博客"indexData.Desc = "入门学习笔记"// 使用给定的数据结构解析模板,并将结果写入werr := t.Execute(w, indexData)fmt.Println(err)
}func main() {server := http.Server{Addr: "127.0.0.1:8080",}http.HandleFunc("/", index)http.HandleFunc("/index", indexHtml)if err := server.ListenAndServe(); err != nil {log.Println(err)}
}
此时访问index
路径,便会看到是页面展示了,不过还没有css
,js
等静态文件渲染,后期会慢慢加上。
三、首页- - -前端文件与后端结构体定义
有了前面的基础知识,我们现在就可以搭建首页啦!
因为本学习笔记主要注重的是后端逻辑,所以前端页面和静态文件等是直接用的已有的,放到项目目录下即可。如果有需要,可以到码云上取:https://gitee.com/lymgoforIT/goblog
首页展示时,有很多数据是从后端获取的,所以我们首先需要定义一些结构体,用于数据渲染,其中有一些通用数据,且基本不怎么变的,我们可以放到配置文件中,而不用存DB
,比如博客系统的标题、标签以及相关系统变量等。
config/config.go
package configtype Viewer struct {Title string // 首页标题Description string // 首页描述Logo string // 博客系统logoNavigation []string // 导航栏Bilibili string // bilibiliAvatar string // 头像UserName string // 用户名UserDesc string // 用户描述
}// 系统相关配置
type SystemConfig struct {AppName stringVersion float32CurrentDir string // 项目路径CdnURL string // cdn地址,用户缓存静态资源QiniuAccessKey string // 使用七牛云存储图片资源QiniuSecretKey stringValine bool // 评论系统用的ValineValineAppid stringValineAppkey stringValineServerURL string
}
其余数据基本是从DB
获取的,与DB
交互的结构体,我们一般会单独建立model
文件夹存放。
models/post.go
package modelsimport ("goblog/config""html/template""time"
)// 用于与DB交互,与DB中字段一一对应
type Post struct {Pid int `json:"pid"` // 文章IDTitle string `json:"title"` // 文章标题Slug string `json:"slug"` // 自定义页面 pathContent string `json:"content"` // 文章的htmlMarkdown string `json:"markdown"` // 文章的MarkdownCategoryId int `json:"categoryId"` //分类idUserId int `json:"userId"` //用户idViewCount int `json:"viewCount"` //查看次数Type int `json:"type"` //文章类型 0 普通,1 自定义文章CreateAt time.Time `json:"createAt"` // 创建时间UpdateAt time.Time `json:"updateAt"` // 更新时间
}// 用于给前端响应,所以有了分类名称和用户名等信息,而不是分类id或者用户id
type PostMore struct {Pid int `json:"pid"` // 文章IDTitle string `json:"title"` // 文章标题Slug string `json:"slug"` // 自定义页面 pathContent template.HTML `json:"content"` // 文章的htmlCategoryId int `json:"categoryId"` // 文章的MarkdownCategoryName string `json:"categoryName"` // 分类名UserId int `json:"userId"` // 用户idUserName string `json:"userName"` // 用户名ViewCount int `json:"viewCount"` // 查看次数Type int `json:"type"` // 文章类型 0 普通,1 自定义文章CreateAt string `json:"createAt"`UpdateAt string `json:"updateAt"`
}type PostReq struct {Pid int `json:"pid"`Title string `json:"title"`Slug string `json:"slug"`Content string `json:"content"`Markdown string `json:"markdown"`CategoryId int `json:"categoryId"`UserId int `json:"userId"`Type int `json:"type"`
}type SearchResp struct {Pid int `orm:"pid" json:"pid"` // 文章IDTitle string `orm:"title" json:"title"`
}type PostRes struct {config.Viewerconfig.SystemConfigArticle PostMore
}
models/home.go
用于封装前端需要的首页数据
package modelsimport "goblog/config"type HomeResponse struct {config.ViewerCategorys []CategoryPosts []PostMoreTotal intPage intPages []intPageEnd bool // 当前页是否是最后一页,决定分页那里是否显示左右箭头
}
四、配置文件加载
这里配置文件我们用的toml
,实际工作中可能yaml
用的更多一点。
config/config.toml
[viewer]Title = "Go语言博客"Description = "Go语言博客"Logo = "/resource/images/logo.png"Navigation = ["首页","/", "GO语言","/golang", "归档","/pigeonhole", "关于","/about"]Bilibili = "https://space.bilibili.com/473844125"Zhihu = "https://www.zhihu.com/people/ma-shen-zhi-lu"Avatar = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13147603927%2F1000.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1647242040&t=c6108010ed46b4acebe18955acdd2d24"UserName = "张三"UserDesc = "长得非常帅的程序员"
[system]CdnURL = "https://static.mszlu.com/goblog/es6/md-assets"QiniuAccessKey = "替换自己的"QiniuSecretKey = "替换自己的"Valine = trueValineAppid = "替换自己的"ValineAppkey = "替换自己的"ValineServerURL = "替换自己的"
toml
文件我们可以使用github.com/BurntSushi/toml
包,获取
go get github.com/BurntSushi/toml
配置文件加载,常规套路是定义全局变量,使用init
加载
config/config.go
package configimport ("os""github.com/BurntSushi/toml"
)var Cfg *TomlConfigfunc init() {Cfg = new(TomlConfig)var err errorCfg.System.CurrentDir, err = os.Getwd()if err != nil {panic(any(err))}Cfg.System.AppName = "lym-go-blog"Cfg.System.Version = 1.0_, err = toml.DecodeFile("config/config.toml", &Cfg)if err != nil {panic(any(err))}
}type TomlConfig struct {Viewer ViewerSystem SystemConfig
}type Viewer struct {Title string // 首页标题Description string // 首页描述Logo string // 博客系统logoNavigation []string // 导航栏Bilibili string // bilibiliAvatar string // 头像UserName string // 用户名UserDesc string // 用户描述
}// 系统相关配置
type SystemConfig struct {AppName stringVersion float32CurrentDir string // 项目路径CdnURL string // cdn地址,用户缓存静态资源QiniuAccessKey string // 使用七牛云存储图片资源QiniuSecretKey stringValine bool // 评论系统用的ValineValineAppid stringValineAppkey stringValineServerURL string
}
五、构造假数据- - -显示首页内容
main.go
注意看代码注释
package mainimport ("goblog/config""goblog/models""html/template""log""net/http""time"
)type IndexData struct {Title string `json:"title"`Desc string `json:"desc"`
}// 前端html页面中使用了一些函数,所以这里需要定义一下
// 是否偶数
func IsODD(num int) bool {return num%2 == 0
}func GetNextName(strs []string, index int) string {return strs[index+1]
}// 日期按指定格式转换
func Date(layout string) string {return time.Now().Format(layout)
}func index(w http.ResponseWriter, r *http.Request) {t := template.New("index.html")// 拿到当前的路径path := config.Cfg.System.CurrentDir//访问博客首页模板的时候,因为有多个模板的嵌套,解析文件的时候,需要将其涉及到的所有模板都进行解析home := path + "/template/home.html"header := path + "/template/layout/header.html"footer := path + "/template/layout/footer.html"personal := path + "/template/layout/personal.html"post := path + "/template/layout/post-list.html"pagination := path + "/template/layout/pagination.html" // 页码// 定义模板中需要用到的函数t.Funcs(template.FuncMap{"isODD": IsODD, "getNextName": GetNextName, "date": Date})t, err := t.ParseFiles(path+"/template/index.html", home, header, footer, personal, post, pagination)if err != nil {log.Println(err)}//页面上涉及到的所有的数据,必须有定义var categorys = []models.Category{{Cid: 1,Name: "go",},{Cid: 2,Name: "python",},}var posts = []models.PostMore{{Pid: 1,Title: "go博客",Content: "这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容",UserName: "张三",ViewCount: 123,CreateAt: "2023-12-17",CategoryId: 1,CategoryName: "go",Type: 0,},{Pid: 2,Title: "这是第二篇博客",Content: "这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容",UserName: "李四",ViewCount: 1314,CreateAt: "2023-12-17",CategoryId: 1,CategoryName: "go",Type: 0,},}var hr = &models.HomeResponse{Viewer: config.Cfg.Viewer,Categorys: categorys,Posts: posts,Total: 2,Page: 1,Pages: []int{1},PageEnd: true,}t.Execute(w, hr)
}func main() {//程序入口,一个项目 只能有一个入口//web程序,http协议 ip portserver := http.Server{Addr: "127.0.0.1:8080",}http.HandleFunc("/", index)// 因为静态文件放到了public/resource目录下,但是页面中写路径的时候都写的resource,所以这里转一下http.Handle("/resource/", http.StripPrefix("/resource/", http.FileServer(http.Dir("public/resource/"))))if err := server.ListenAndServe(); err != nil {log.Println(err)}
}
此时通过流量器访问8080
端口,便可看到如下界面了
相关文章:
go原生http开发简易blog(一)项目简介与搭建
文章目录 一、项目简介二、项目搭建前置知识三、首页- - -前端文件与后端结构体定义四、配置文件加载五、构造假数据- - -显示首页内容 代码地址:https://gitee.com/lymgoforIT/goblog 一、项目简介 使用Go原生http开发一个简易的博客系统,包含一下功能…...
[足式机器人]Part4 南科大高等机器人控制课 Ch09 Dynamics of Open Chains
本文仅供学习使用 本文参考: B站:CLEAR_LAB 笔者带更新-运动学 课程主讲教师: Prof. Wei Zhang 南科大高等机器人控制课 Ch09 Dynamics of Open Chains 1. Introduction1.1 From Single Rigid Body to Open Chains1.2 Preview of Open-Chain …...
概率论复习
第一章:随机概率及其概率 A和B相容就是 AB 空集 全概率公式与贝叶斯公式: 伯努利求概率: 第二章:一维随机变量及其分布: 离散型随机变量求分布律: 利用常规离散性分布求概率: 连续性随机变量…...
ES客户端RestHighLevelClient的使用
1 RestHighLevelClient介绍 默认情况下,ElasticSearch使用两个端口来监听外部TCP流量。 9200端口:用于所有通过HTTP协议进行的API调用。包括搜索、聚合、监控、以及其他任何使用HTTP协议的请求。所有的客户端库都会使用该端口与ElasticSearch进行交互。…...
GitHub入门命令介绍
GitHub是当今最受欢迎的代码托管平台之一,它提供了强大的版本控制和协作功能。 对于初学者来说,熟悉GitHub的基本命令非常重要。下面介绍一些常用的GitHub命令。 一、安装Git 1. Windows系统:在Windows上使用GitHub之前,您需要先…...
EasyExcel 简单导入
前边写过使用easyexcel进行简单、多sheet页的导出。今天周日利用空闲写一下对应简单的导入。 重点:springboot、easyExcel、桥接模式; 说明:本次使用实体类student:属性看前边章节内容; 1、公共导入service public …...
Termux搭建nodejs环境
安装nodejs ~ $ pkg install nodejs使用http-server搭建文件下载服务 先安 http-server 并启动 # 安装 http-server 包 ~ $ npm install -g http-server# 启动 http-server 服务 ~ $ http-server Starting up http-server, serving ./http-server version: 14.1.1http-serve…...
喜报丨迪捷软件入选2023年浙江省信息技术应用创新典型案例
12月6日,浙江省经信厅公示了2023年浙江省信息技术应用创新典型案例入围名单。本次案例征集活动,由浙江省经信厅、省密码管理局、工业和信息化部网络安全产业发展中心联合组织开展,共遴选出24个优秀典型解决方案,迪捷软件“基于全数…...
C语言连接zookeeper客户端(不能完全参考官网教程)
准备过程 1.通过VStudio 远程连接linux的开发环境; 2.g环境,通过MingW安装; 3.必须要安装好pthread.h的环境,不管是windows端(linux 可视化端开发就不管这个)还是linux端; 4.需要准备zookeeper…...
python排序
0. 背景 Python排序功能十分强大,可以进行基本排序或自定义排序。Python中提供两种不同的排序方法对各种各样的数据类型进行排序。 1. 使用sorted()函数排序 排序主要是对相同数据类型的元素进行的,包括数值和字符串两种数据类型。 1.1 对数值进行排…...
【Spark精讲】Spark Shuffle详解
目录 Shuffle概述 Shuffle执行流程 总体流程 中间文件 ShuffledRDD生成 Stage划分 Task划分 Map端写入(Shuffle Write) Reduce端读取(Shuffle Read) Spark Shuffle演变 SortShuffleManager运行机制 普通运行机制 bypass 运行机制 Tungsten Sort Shuffle 运行机制…...
【C++初阶】八、初识模板(泛型编程、函数模板、类模板)
相关代码gitee自取: C语言学习日记: 加油努力 (gitee.com) 接上期: 【C初阶】七、内存管理 (C/C内存分布、C内存管理方式、operator new / delete 函数、定位new表达式) -CSDN博客 目录 一 . 泛型编程 二 . 函数模板 函数模板…...
珠海数字孪生赋能工业智能制造,助力制造业企业数字化转型
珠海数字孪生赋能工业智能制造,助力制造业企业数字化转型。数字孪生是利用物理模型、传感器更新及运行历史数据,集成多物理量、多尺度的仿真过程。巨蟹数科数字孪生通过构建物理车间与虚拟车间之间的有效映射并实时反馈机制,实现物理车间与虚…...
HarmonyOS开发实战:如何实现一个运动排名榜页面
HarmonyOS开发实战:如何实现一个运动排名榜页面 代码仓库: 运动排名榜页面 项目介绍 本项目使用声明式语法和组件化基础知识,搭建一个可刷新的排行榜页面。在排行榜页面中,使用循环渲染控制语法来实现列表数据渲染,…...
2019年第八届数学建模国际赛小美赛D题安全选举的答案是什么解题全过程文档及程序
2019年第八届数学建模国际赛小美赛 D题 安全选举的答案是什么 原题再现: 随着美国进入一场关键性的选举,在确保投票系统的完整性方面进展甚微。2016年总统大选期间,唐纳德特朗普因被指控受到外国干涉而入主白宫,这一问题再次成为…...
vivado 创建实施约束
创建实施约束 在您有了一个合成的网表之后,您可以将它与XDC文件一起加载到内存中,或者Tcl脚本已启用以进行实现。当加载XDC以便验证和更正任何不能应用的约束。在某些情况下,合成网表中的对象名称与精心设计。如果是这种情况,则必…...
【代码分析】MPI
代码解读 问题 model/AdaMPI.py:21 为什么下降分辨率model.CPN.unet.FeatMaskNetwork 为什么用的是mask,unet? MPI class MPIPredictor(nn.Module):def __init__(self,width384,height256,num_planes64,):super(MPIPredictor, self).__init__()self.…...
数字孪生Web3D智慧机房可视化运维云平台建设方案
前言 进入信息化时代,数字经济发展如火如荼,数据中心作为全行业数智化转型的智慧基座,重要性日益凸显。与此同时,随着东数西算工程落地和新型算力网络体系构建,数据中心建设规模和业务总量不断增长,机房管理…...
飞天使-docker知识点12-docker-compose
文章目录 docker-compose命令启动单个容器重启容器停止和启动容器停止和启动所有容器演示一个简单示范 docker-compose 部署有依赖问题 Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它允许您使用简单的 YAML 文件来配置应用程序的服务、网络和存储等方…...
快速排序(一)
目录 快速排序(hoare版本) 初级实现 问题改进 中级实现 时空复杂度 高级实现 三数取中 快速排序(hoare版本) 历史背景:快速排序是Hoare于1962年提出的一种基于二叉树思想的交换排序方法 基本思想:…...
GO的sql注入盲注脚本
之间学习了go的语法 这里就开始go的爬虫 与其说是爬虫 其实就是网站的访问如何实现 因为之前想通过go写sql注入盲注脚本 发现不是那么简单 这里开始研究一下 首先是请求网站 这里貌似很简单 package mainimport ("fmt""net/http" )func main() {res, …...
写好ChatGPT提示词原则之:清晰且具体(clear specific)
ChatGPT 的优势在于它允许用户跨越机器学习和深度学习的复杂门槛,直接利用已经训练好的模型。然而,即便是这些先进的大型语言模型也面临着上下文理解和模型固有局限性的挑战。为了最大化这些大型语言模型(LLM)的潜力,关…...
Java实现快速排序及其动图演示
快速排序(Quicksort)是一种基于分治思想的排序算法。它通过选择一个基准元素,将数组分为两个子数组,其中一个子数组的所有元素都小于基准元素,另一个子数组的所有元素都大于基准元素,然后递归地对这两个子数…...
iClient3D 图元操作
1. S3MTilesLayer,S3M(Spatial 3D Model)图层类 S3MTilesLayer,S3M(Spatial 3D Model)图层类,通过该图层实现加载三维切片缓存,包括倾斜摄影模型、BIM模型、点云数据、精细模型、矢量数据、符号等。 那S3MTilesLayer中针对图元的…...
从0到1!开发小白快速入门腾讯云数据库
在这个海量数据大爆发的时代,一个单一的开源数据库产品往往很难直接满足企业的业务需求,在某些场景下,无论是性能、安全还是稳定性,都面临着各种各样的问题。 你在工作中也有这样的烦恼的话,一定是因为你还没有使用过…...
Golang清晰代码指南
发挥易读和易维护软件的好处 - 第一部分 嗨,开发者们,清晰的代码是指编写易于阅读、理解和维护的软件代码。它是遵循一组原则和实践,优先考虑清晰性、简单性和一致性的代码。清晰的代码旨在使代码库更易管理,减少引入错误的可能性…...
C语言 文件I/O(备查)
所有案列 跳转到其他。 文件打开 FILE* fopen(const char *filename, const char *mode); 参数:filename:指定要打开的文件名,需要加上路径(相对、绝对路径)mode:指定文件的打开模式 返回值:成…...
web(HTML之表单练习)
使用HTML实现该界面: 要求如下: 用户名为文本框,名称为 UserName,长度为 15,最大字符数为 20。 密码为密码框,名称为 UserPass,长度为 15,最大字符数为 20。 性别为两个单选按钮&a…...
通过对象轮换实现 LRU 缓存结构
文章目录 通过两个对象轮换,按照是否访问实现内容长久保存rollup 的缓存实现 export default function (max) { //max 缓存容量var num, curr, prev;var limit max || 1;function keep(key, value) {if (num > limit) {prev curr; // 超过容量时当前对象变成缓…...
【Unity动画】综合案例完结-控制角色动作播放+声音配套
这个案例实现的动作并不复杂,主要包含一个 跳跃动作、攻击动作、还有一个包含三个动画状态的动画混合树。然后设置三个参数来控制切换。 状态机结构如下: 完整代码 using System.Collections; using System.Collections.Generic; using UnityEngine;pu…...
公司网站开发费计入办公费/google广告
最近在折腾价格时间序列的预测,用了若干种算法,这次先把ARIMA放上来。其实ARIMA做时间序列预测,R语言里有个autoarima包就又快又好,但是自己想练习python并且不信邪就折腾了,结果真的折腾了。。。虽然理论上是pip inst…...
哈尔滨市建委官网道路建设/福州seo公司排名
正文 现在市面上的算法资料也五花八门,种类繁多,小编也整理了一份不同于市面且有意思的算法资料,不能说多全面,但是是小编花了很长时间整理归纳出来的,自我感觉还行。分享给同事及群里反响都不错,所以小编…...
石湾做网站/网站推广应该怎么做?
👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇作者丨小集来源丨小集(ID:zsxjtip)苹果在 WWDC22 期间,同步更新了一版 《App Store 审查指南》。更新《App Store 审查…...
初学者怎么做php网站/杭州推广公司排名
Dock栏优化工具在哪下载?小编今天为大家带来了MultiDock for Mac软件,帮助您将应用程序、文件和文件夹组织成多个类似dock的面板,并将它们固定在屏幕边缘或自由移动。 multidock mac破解版安装步骤 在macdown下载完MultiDock Mac破解版软件…...
10种网络营销方式/南昌seo排名扣费
原创、转载请注明出处 一、结构 二叉树有2类表示方法:链式和数组模拟。 其中数组模拟有2种:1.一个数组,数组下标代表完全二叉树的编号,对于普通二叉树,没有结点的为空,有节点的地方数组值为二叉树权值。 2.…...
重庆做网站哪个好些嘛/网站备案是什么意思
前言 接上一篇的双索引问题 1、给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。 示例: 输入: s 7, nums [2,3,1,2,4,3] 输出: 2 解释: 子数组 [4,3] 是…...