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

1 创建博文

1.1 在main.go中添加路由

在这里插入图片描述
访问http://localhost:3000/articles/create
在这里插入图片描述

1.2 构建表单

在这里插入图片描述
报错
在这里插入图片描述
router在main函数中定义,但其他函数无法直接识别,需将router定义在函数体外面当成全局变量(包级别的变量)。
在这里插入图片描述
包级别的变量不能使用:=声明并赋值变量
应该使用

var router = mux.NewRouter( )

浏览器访问 localhost:3000/articles/create
在这里插入图片描述
浏览器中查看源码
在这里插入图片描述

2 读取表单数据

2.1 完善articlesStoreHandler() 函数

func articlesStoreHandler(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil{
		//解析错误,这里应该有错误处理
		fmt.Fprintf(w,"请提供正确的数据!")
		return
	}

	title := r.PostForm.Get("title")

	fmt.Fprintf(w,"POST PostForm: %v <br>",r.PostForm)
	fmt.Fprintf(w,"POST Form: %v <br>",r.Form)
	fmt.Fprintf(w,"title 的值为: %v <br>", title)
}

访问 localhost:3000/articles/create ,在标题和内容里输入信息:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.2 修改代码,查看区别

.
.
.
func articlesCreateHandler(w http.ResponseWriter, r *http.Request) {
    html := `
<!DOCTYPE html>
<html lang="en">
<head>
    <title>创建文章 —— 我的技术博客</title>
</head>
<body>
    <form action="%s?test=data" method="post">
        <p><input type="text" name="title"></p>
        <p><textarea name="body" cols="30" rows="10"></textarea></p>
        <p><button type="submit">提交</button></p>
    </form>
</body>
</html>
`
    storeURL, _ := router.Get("articles.store").URL()
    fmt.Fprintf(w, html, storeURL)
}
.
.
.

重新打开 localhost:3000/articles/create 并填写数据(注意如果你使用浏览器的回退功能的话,需要重新刷新页面),再次提交:

在这里插入图片描述
Form多了URL参数里的数据

如不想获取所有的请求内容,而是逐个获取的话,这也是比较常见的操作,无需使用 r.ParseForm() 可直接使用 r.FormValue() 和 r.PostFormValue() 方法:

.
.
.
func articlesStoreHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "r.Form 中 title 的值为: %v <br>", r.FormValue("title"))
    fmt.Fprintf(w, "r.PostForm 中 title 的值为: %v <br>", r.PostFormValue("title"))
    fmt.Fprintf(w, "r.Form 中 test 的值为: %v <br>", r.FormValue("test"))
    fmt.Fprintf(w, "r.PostForm 中 test 的值为: %v <br>", r.PostFormValue("test"))
}
.
.
.

在这里插入图片描述

3 表单验证

3.1 数据验证

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

    title := r.PostFormValue("title")
    body := r.PostFormValue("body")

    errors := make(map[string]string)

    // 验证标题
    if title == "" {
        errors["title"] = "标题不能为空"
    } else if len(title) < 3 || len(title) > 40 {
        errors["title"] = "标题长度需介于 3-40"
    }

    // 验证内容
    if body == "" {
        errors["body"] = "内容不能为空"
    } else if len(body) < 10 {
        errors["body"] = "内容长度需大于或等于 10 个字节"
    }

    // 检查是否有错误
    if len(errors) == 0 {
        fmt.Fprint(w, "验证通过!<br>")
        fmt.Fprintf(w, "title 的值为: %v <br>", title)
        fmt.Fprintf(w, "title 的长度为: %v <br>", len(title))
        fmt.Fprintf(w, "body 的值为: %v <br>", body)
        fmt.Fprintf(w, "body 的长度为: %v <br>", len(body))
    } else {
        fmt.Fprintf(w, "有错误发生,errors 的值为: %v <br>", errors)
    }
}
.
.
.

errors := make(map[string]string)
这行代码的含义是创建了一个空的map,其中键的类型为string,值的类型也为string。这个map被命名为errors。

访问并输入数据
在这里插入图片描述

在这里插入图片描述
在Java中,一个汉字通常占用两个字节,因为Java中使用的是UTF-16编码,每个字符通常占用16位,即2个字节。这使得Java中处理Unicode字符和汉字比较方便。

在Go语言中,一个汉字通常占用3个字节,因为Go语言中的字符串是以UTF-8格式保存的,而UTF-8编码中一个汉字通常由3个字节表示。

若要按字符个数计算而非字节数,可以使用Go语言中的utf8包中的RuneCountInString()函数来计算。这个函数会返回字符串中Unicode字符的个数,而不是字节数。

修改代码

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

    title := r.PostFormValue("title")
    body := r.PostFormValue("body")

    errors := make(map[string]string)

    // 验证标题
    if title == "" {
        errors["title"] = "标题不能为空"
    } else if utf8.RuneCountInString(title) < 3 || utf8.RuneCountInString(title) > 40 {
        errors["title"] = "标题长度需介于 3-40"
    }

    // 验证内容
    if body == "" {
        errors["body"] = "内容不能为空"
    } else if utf8.RuneCountInString(body) < 10 {
        errors["body"] = "内容长度需大于或等于 10 个字节"
    }

    // 检查是否有错误
    if len(errors) == 0 {
        fmt.Fprint(w, "验证通过!<br>")
        fmt.Fprintf(w, "title 的值为: %v <br>", title)
        fmt.Fprintf(w, "title 的长度为: %v <br>", utf8.RuneCountInString(title))
        fmt.Fprintf(w, "body 的值为: %v <br>", body)
        fmt.Fprintf(w, "body 的长度为: %v <br>", utf8.RuneCountInString(body))
    } else {
        fmt.Fprintf(w, "有错误发生,errors 的值为: %v <br>", errors)
    }
}
.
.
.

网页验证
在这里插入图片描述

在这里插入图片描述

3.2 出错提示

数据验证的逻辑

  1. 正确则存入数据库
  2. 错误则重新显示表单,并显示错误提示

erros大于0时,我们需要将错误信息的参数渲染到HTML中,html/template标准库专门设计解决这种场景。

.
.
.
// ArticlesFormData 创建博文表单数据
type ArticlesFormData struct {
    Title, Body string
    URL         *url.URL
    Errors      map[string]string
}

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

    // 检查是否有错误
    if len(errors) == 0 {
        .
        .
        .
    } else {

        html := `
<!DOCTYPE html>
<html lang="en">
<head>
    <title>创建文章 —— 我的技术博客</title>
    <style type="text/css">.error {color: red;}</style>
</head>
<body>
    <form action="{{ .URL }}" method="post">
        <p><input type="text" name="title" value="{{ .Title }}"></p>
        {{ with .Errors.title }}
        <p class="error">{{ . }}</p>
        {{ end }}
        <p><textarea name="body" cols="30" rows="10">{{ .Body }}</textarea></p>
        {{ with .Errors.body }}
        <p class="error">{{ . }}</p>
        {{ end }}
        <p><button type="submit">提交</button></p>
    </form>
</body>
</html>
`
        storeURL, _ := router.Get("articles.store").URL()

        data := ArticlesFormData{
            Title:  title,
            Body:   body,
            URL:    storeURL,
            Errors: errors,
        }
        tmpl, err := template.New("create-form").Parse(html)
        if err != nil {
            panic(err)
        }

        err = tmpl.Execute(w, data)
        if err != nil {
            panic(err)
        }
    }
}
.
.
.

首先我们定义一个 ArticlesFormData struct,用以给模板文件传输变量时使用。
接下来是构建 ArticlesFormData 里的数据,storeURL 是通过路由参数生成的 URL 路径。

在这里插入图片描述


相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-10 11:28:08       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-10 11:28:08       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-10 11:28:08       82 阅读
  4. Python语言-面向对象

    2024-05-10 11:28:08       91 阅读

热门阅读

  1. 机器视觉在锂电芯生产中的全方位检测应用

    2024-05-10 11:28:08       27 阅读
  2. redis+SQL server等保测评命令

    2024-05-10 11:28:08       33 阅读
  3. 情感分类学习笔记(2)

    2024-05-10 11:28:08       35 阅读
  4. 列存储数据库之MonetDB

    2024-05-10 11:28:08       32 阅读
  5. 冒泡排序(Bubble Sort)

    2024-05-10 11:28:08       30 阅读
  6. TrinityCore最新版本master安装@ubuntu22@win10

    2024-05-10 11:28:08       24 阅读