【go项目01_学习记录11】

news2024/7/2 3:27:11

操作数据库

  • 1 文章列表
  • 2 删除文章

1 文章列表

(1)先保证文章已经有多篇,可以直接在数据库中添加,或者访问链接: localhost:3000/articles/create,增加几篇文章。
在这里插入图片描述
(2)之前设置好了articles.index 路由,访问 localhost:3000/articles 显示文章列表
在这里插入图片描述
(3)完善articlesIndexHandler()使之能够显示数据库中的数据

.
.
.
func articlesIndexHandler(w http.ResponseWriter, r *http.Request) {
    // 1. 执行查询语句,返回一个结果集
    rows, err := db.Query("SELECT * from articles")
    checkError(err)
    defer rows.Close()

    var articles []Article
    //2. 循环读取结果
    for rows.Next() {
        var article Article
        // 2.1 扫描每一行的结果并赋值到一个 article 对象中
        err := rows.Scan(&article.ID, &article.Title, &article.Body)
        checkError(err)
        // 2.2 将 article 追加到 articles 的这个数组中
        articles = append(articles, article)
    }

    // 2.3 检测遍历时是否发生错误
    err = rows.Err()
    checkError(err)

    // 3. 加载模板
    tmpl, err := template.ParseFiles("resources/views/articles/index.gohtml")
    checkError(err)

    // 4. 渲染模板,将所有文章的数据传输进去
    err = tmpl.Execute(w, articles)
    checkError(err)
}
.
.
.

添加模板
resources/views/articles/index.gohtml

<!DOCTYPE html>
<html lang="en">
<head>
    <title>所有文章 —— 我的技术博客</title>
    <style type="text/css">.error {color: red;}</style>
</head>
<body>
    <h1>所有文章</h1>
    <ul>
        {{ range $key, $article := . }}
            <li><a href=""><strong>{{ $article.ID }}</strong>: {{ $article.Title }}</a></li>
        {{ end }}
    </ul>
</body>
</html>

访问 localhost:3000/articles
在这里插入图片描述
为列表里的文章加上链接

.
.
'
// Article  对应一条文章数据
type Article struct {
    .
    .
    .
}

// Link 方法用来生成文章链接
func (a Article) Link() string {
    showURL, err := router.Get("articles.show").URL("id", strconv.FormatInt(a.ID, 10))
    if err != nil {
        checkError(err)
        return ""
    }
    return showURL.String()
}
.
.
.

保存后刷新页面并查看页面源码:

在这里插入图片描述

2 删除文章

先开发后台的删除逻辑,然后在文章详情页里显示删除按钮
(1)注册articles.delete 路由
在这里插入图片描述
(2)添加articlesDeleteHandler()函数

.
.
.
func articlesDeleteHandler(w http.ResponseWriter, r *http.Request) {

    // 1. 获取 URL 参数
    id := getRouteVariable("id", r)

    // 2. 读取对应的文章数据
    article, err := getArticleByID(id)

    // 3. 如果出现错误
    if err != nil {
        if err == sql.ErrNoRows {
            // 3.1 数据未找到
            w.WriteHeader(http.StatusNotFound)
            fmt.Fprint(w, "404 文章未找到")
        } else {
            // 3.2 数据库错误
            checkError(err)
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, "500 服务器内部错误")
        }
    } else {
        // 4. 未出现错误,执行删除操作
        rowsAffected, err := article.Delete()

        // 4.1 发生错误
        if err != nil {
            // 应该是 SQL 报错了
            checkError(err)
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, "500 服务器内部错误")
        } else {
            // 4.2 未发生错误
            if rowsAffected > 0 {
                // 重定向到文章列表页
                indexURL, _ := router.Get("articles.index").URL()
                http.Redirect(w, r, indexURL.String(), http.StatusFound)
            } else {
                // Edge case
                w.WriteHeader(http.StatusNotFound)
                fmt.Fprint(w, "404 文章未找到")
            }
        }
    }
}

添加Article 的 Delete() 方法 ,上面代码块用到了Delete方法


// // 为 Article 添加一个 Delete 方法,删除文章
func (a Article) Delete() (rowsAffected int64, err error) {
    rs, err := db.Exec("DELETE FROM articles WHERE id = " + strconv.FormatInt(a.ID, 10))

    if err != nil {
        return 0, err
    }

    // √ 删除成功
    if n, _ := rs.RowsAffected(); n > 0 {
        return n, nil
    }

    return 0, nil
}


(3)文章详情页面添加删除按钮

.
.
.
func  articlesShowHandler(w http.ResponseWriter, r *http.Request) {
    .
    .
    .
    // 3. 如果出现错误
    if err !=  nil {
        .
        .
        .
    } else {
        // 4. 读取成功,显示文章
        tmpl, err := template.New("show.gohtml").
            Funcs(template.FuncMap{
                "RouteName2URL": RouteName2URL,
                "Int64ToString": Int64ToString,
            }).
            ParseFiles("resources/views/articles/show.gohtml")
        checkError(err)
        err = tmpl.Execute(w, article)
        checkError(err)
    }
}

template.New() 先初始化,然后使用 Funcs() 注册函数,再使用 ParseFiles (),需要注意的是 New() 的参数是模板名称,需要对应 ParseFiles() 中的文件名,否则会无法正确读取到模板,最终显示空白页面。

创建上面代码中的两个函数RouteName2URL 和 Int64ToString

.
.
.
// RouteName2URL 通过路由名称来获取 URL
func RouteName2URL(routeName string, pairs ...string) string {
    url, err := router.Get(routeName).URL(pairs...)
    if err != nil {
        checkError(err)
        return ""
    }

    return url.String()
}

// Int64ToString 将 int64 转换为 string
func Int64ToString(num int64) string {
    return strconv.FormatInt(num, 10)
}

func (a Article) Delete() (rowsAffected int64, err error) {
.
.
.

修改模板 show.gohtml

<!DOCTYPE html>
<html lang="en">

<head>
    <title>{{ .Title }} —— 我的技术博客</title>
    <style type="text/css">
        .error {
            color: red;
        }
    </style>
</head>

<body>
    <p>ID: {{ .ID }}</p>
    <p>标题: {{ .Title }}</p>
    <p>内容:{{ .Body }}</p>

    {{/* 构建删除按钮  */}}
    {{ $idString := Int64ToString .ID  }}
    <form action="{{ RouteName2URL "articles.delete" "id" $idString }}" method="post">
        <button type="submit" onclick="return confirm('删除动作不可逆,请确定是否继续')">删除</button>
    </form>

</body>

</html>

在这里插入图片描述
打开articles.show文章详情页localhost:3000/articles/4
在这里插入图片描述
在这里插入图片描述
点击删除,确定删除
在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1672704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移动端自动化测试工具 Appium 之自定义报告

文章目录 一、背景二、具体实现1、保存结果实体2、工具类3、自定义报告监听类代码4、模板代码4.1、report.vm4.2、执行xml 三、总结 一、背景 自动化测试用例跑完后报告展示是体现咱们价值的一个地方咱们先看原始报告。 上面报告虽然麻雀虽小但五脏俱全&#xff0c;但是如果用…

JavaScript 进阶(一)

一、作用域 1. 局部作用域 &#xff08;1&#xff09;函数作用域 、 &#xff08;2&#xff09;块作用域 2. 全局作用域 3. 作用域链 g 作用域可以访问 f 作用域&#xff08;子访问父&#xff09;&#xff0c;但是 f 作用域&#xff0c;不能访问 g 作用域&#xff08;父…

[数据集][图像分类]杂草分类数据集17509张9类别

数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;17509 分类类别数&#xff1a;9 类别名称:["chineseapple","lantana","negatives","parkinsonia","part…

经典面试题---环形链表

1. 环形链表1. - 力扣&#xff08;LeetCode&#xff09; 要解决这道题&#xff0c;我们首先要挖掘出带环的链表与不带环的链表之间的差别。 以此&#xff0c;才能设计出算法来体现这种差别并判断。 二者最突出的不同&#xff0c;就是不带环的链表有尾结点&#xff0c;也就是说…

Springboot打包jar如何后台启动和查看日志?

如何后台启动Spring Boot的fat jar 使用nohup命令启动&#xff1a; 在Linux或Unix系统中&#xff0c;你可以使用nohup命令来启动jar包&#xff0c;以确保即使你关闭了终端或断开了SSH连接&#xff0c;程序仍然可以在后台运行。命令格式如下&#xff1a;nohup java -jar yourapp…

C语言(指针)6

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

opencv车道偏离系统-代码+原理-人工智能-自动驾驶

车道偏离预警系统&#xff08;Lane Departure Warning System, LDWS&#xff09;是一种主动安全技术&#xff0c;旨在帮助驾驶员避免因无意中偏离车道而引发的事故。从原理到实战应用&#xff0c;其工作流程大致如下&#xff1a; 传感器采集 &#xff1a;系统通常配备有一个或…

智能终端RK3568主板在智慧公交条形屏项目的应用,支持鸿蒙,支持全国产化

基于AIoT-3568A的智慧公交条形屏&#xff0c;可支持公交线路动态展示&#xff0c;语音到站提醒&#xff0c;减少过乘、漏乘的情况&#xff0c;有效提高了公交服务效率和质量&#xff0c;为乘客提供了更舒适、更安全和更方便的出行体验&#xff0c;为城市的发展增添了新的活力。…

升级Microsoft 365后,SAP GUI中无法打开Excel的解决方案

最近&#xff0c;我们遇到了一个棘手的问题&#xff0c;一位客户在升级到Microsoft 365后&#xff0c;无法在SAP GUI中打开Excel。这个问题不仅影响了工作效率&#xff0c;也给用户的日常操作带来了不便。在本文中&#xff0c;我们将探讨问题的成因&#xff0c;并提供一种解决方…

纯福利|手把手教你如何白嫖免费的GPU资源(二)

大家好&#xff0c;我是无界生长。 前段时间写过一篇文章《纯福利&#xff5c;手把手教你如何白嫖免费的GPU资源&#xff08;一&#xff09;》&#xff0c;使用Google Colab提供的免费的GPU资源&#xff0c;今天接着写白嫖GPU资源攻略&#xff0c;可获得“长期免费的CPU实例资源…

Redis:分布式系统

文章目录 认识RedisRedis和MySQLRedis的场景Redis的设计 分布式单机架构应用数据分离架构应用服务集群架构 认识Redis 在开始Redis学习前&#xff0c;要先认识一下Redis Redis的设计&#xff0c;是想要把它当做是一个数据库&#xff0c;一个缓存&#xff0c;或者说是一个消息…

AI时代的网络安全战:以智取胜,守护数字安宁

在数字化浪潮的推动下&#xff0c;我们的生活和工作日益离不开互联网。然而&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;网络安全问题也日益凸显。美国联邦调查局&#xff08;FBI&#xff09;的一则警报如同一记重锤&#xff0c;敲响了我们对…

无尘室手套的选定标准

无尘室手套的选定标准主要包括以下几个方面&#xff1a; 材料选择&#xff1a; 考虑与应用的相容性&#xff0c;例如某些化学品可能对某些材料产生反应。是否存在乳胶过敏也是一个重要的考虑因素。常见的选择包括丁腈手套&#xff0c;它们通常比乳胶手套更耐用且化学稳定性更…

【爬虫】爬取股票历史K线数据写入数据库(三)

前几天有写过两篇&#xff1a; 【爬虫】爬取A股数据写入数据库&#xff08;二&#xff09; 【爬虫】爬取A股数据写入数据库&#xff08;一&#xff09; 现在继续完善&#xff0c;分析及爬取股票的历史K线数据通过ORM形式批量写入数据库。 2024/05&#xff0c;本文主要内容如下…

Vue的学习 —— <vue响应式基础>

目录 前言 正文 单文件组件 什么是单文件组件 单文件组件使用方法 数据绑定 什么是数据绑定 数据绑定的使用方法 响应式数据绑定 响应式数据绑定的使用方法 ref() 函数 reactive()函数 toRef()函数 toRefs()函数 案例练习 前言 Vue.js 以其高效的数据绑定和视图…

Nginx - location中的匹配规则和动态Proxy

文章目录 官网location 规则详解动态Proxy使用多个 if 指令指定不同的 proxy_pass根据参数选择不同的 proxy_pass 官网 https://nginx.org/en/docs/http/ngx_http_core_module.html#location location 规则详解 Nginx的location指令工作原理如下&#xff1a; 位置匹配&#…

【中级软件设计师】上午题3-数据结构(查漏补缺版)

上午题3-数据结构 0 前言1 时间、空间复杂度2 串2.1 串的模式匹配 3 矩阵4 图4.1 邻接矩阵和邻接表 5 查找6 哈希表、7 树7.1 B树 0 前言 因为我之前考研系统地学习过数据结构和操作系统&#xff0c;这两部分的笔记不完整 1 时间、空间复杂度 指数<阶乘<n次方阶 使用队…

Java入门基础学习笔记22——程序流程控制

程序流程控制&#xff1a;控制程序的执行顺序。 程序有哪些执行顺序&#xff1f; 顺序、分支和循环。 分支结构&#xff1a; if、switch 循环&#xff1a; for、while、do-while 顺序结构是程序中最简单最基本的流程控制&#xff0c;没有特定的语法结构&#xff0c;按照代码…

01-02-5

1、单链表中按位置查找 a.原理 通过传递的位置&#xff0c;返回该位置对应的地址&#xff0c;放到主函数定义的指针变量中。 我们认为位置从&#xff1a;有数据的节点开始计数 即如下结构&#xff1a; 查找位置&#xff0c;就是返回该位置对应的空间地址。 b.代码说明 Ⅰ…

深度剖析深度神经网络(DNN):原理、实现与应用

目录 引言 一、DNN基本原理 二、DNN核心算法原理 三、DNN具体操作步骤 四、代码演示 引言 在人工智能和机器学习的浪潮中&#xff0c;深度神经网络&#xff08;Deep Neural Network&#xff0c;简称DNN&#xff09;已经成为了一种非常重要的工具。DNN模仿人脑神经网络的结…