ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

换个语言学一下 Golang (13)——Web表单处理

2019-07-04 11:43:39  阅读:382  来源: 互联网

标签:Web 13 http Form fmt 表单 Golang login friend


介绍

表单是我们平常编写Web应用常用的工具,通过表单我们可以方便的让客户端和服务器进 行数据的交互。对于以前开发过Web的用户来说表单都非常熟悉。
表单是一个包含表单元素的区域。表单元素是允许用户在表单中(比如:文本域、下拉列表、 单选框、复选框等等)输入信息的元素。表单使用表单标签(<form>)定义。

1、处理表单的输入

先看一个例子吧。

注意:所有文件要放在src文件夹下
在之前文章的代码基础之下,创建一个view文件夹,用来存放界面的代码文件,在view文件中创建一个login.ctpl文件,用来写前端代码,后缀名可根据自己喜好自定义。下面看下这个文件内的代码:

<html>
<head>
    <title>登录</title>
</head>
<body>
    <form action="http://localhost:9090/login" method="post">
        用户名:<input type="text" name="username"> 
        密码:<input type="password" name="password">
        <input type="submit" value="登陆">
    </form>
</body>
</html>

从代码中可知,我们的界面非常简单,就是个简单的用户名,密码的表单,且通过Post方法提交到http://localhost:9090/login

然后我们再看一下这个后端对于login的处理,同样在之前的代码基础上,在myserver.go文件中添加一个login的函数。
代码如下:

package webserver

import (
    "fmt"
    "net/http"
    "text/template"
)

func login(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() //解析form
    fmt.Println("method: ", r.Method)
    //判断传递方式
    if r.Method == "GET" {
        //加载界面模板
        t, _ := template.ParseFiles("./view/login.ctpl")
        //将解析好的模板应用到data上,这里data为nil
        t.Execute(w, nil)
    } else if r.Method == "POST" {
        fmt.Println("username: ", r.Form["username"])
        fmt.Println("password: ", r.Form["password"])
    }
}

当代码执行到login函数的时候,首先我们要判断是通过什么方式传递过来的,是GET,还是POST。这个我们可以在r.Method 中取得,然后根据不同的方法分别处理。

在get方法中,我们调用了html/template包中的2个函数,下面看下这两个函数的定义吧:

  • ParseFiles
func (t *Template) ParseFiles(filenames ...string) (*Template, error)

ParseFiles方法解析filenames指定的文件里的模板定义并将解析结果与t关联。如果发生错误,会停止解析并返回nil,否则返回(t, nil)。至少要提供一个文件。

  • Execute
func (t *Template) Execute(wr io.Writer, data interface{}) error

Execute方法将解析好的模板应用到data上,并将输出写入wr。如果执行时出现错误,会停止执行,但有可能已经写入wr部分数据。模板可以安全的并发执行。

在Post方法中,这里只是做了简单的控制台打印,检测是否跟我们输入的一致。

好,我们的login函数写好了,那么我们怎么调用呢?当然是路由喽,在之前的自定义的路由中加入一个新的路由,补充myserver.go中的ServeHTTP代码如下:

type MyMux struct {
}

func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/login" { login(w, r) return } http.NotFound(w, r) return }

然后运行,跑起来。浏览器地址栏中输入:http://localhost:9090/login,结果如下:

在页面中输入:用户名:chain 密码:123456 并点击登录按钮。控制台结果如下:

如图所示,我们打印出来了我们的输入。

request.Form是一个url.Values类型,里面存储的是对应的类似key=value的信息,下面 展示了可以对form数据进行的一些操作:

 

v := url.Values{}
v.Set("name", "Ava")
v.Add("friend", "Jess")
v.Add("friend", "Sarah") v.Add("friend", "Zoe")
// v.Encode() == "name=Ava&friend=Jess&friend=Sarah&friend=Zoe"
fmt.Println(v.Get("name"))
fmt.Println(v.Get("friend"))
fmt.Println(v["friend"])

 

Tips: Request本身也提供了FormValue()函数来获取用户提交的参数。如 r.Form[“username”]也可写成r.FormValue(“username”)。调用r.FormValue时会自动调用 r.ParseForm,所以不必提前调用。r.FormValue只会返回同名参数中的第一个,若参数不存 在则返回空字符串。

 

2、验证表单的输入

开发Web的一个原则就是,不能信任用户输入的任何信息,所以验证和过滤用户的输入信 息就变得非常重要,我们经常会在微博、新闻中听到某某网站被入侵了,存在什么漏洞,这 些大多是是因为网站对于用户输入的信息没有做严格的验证引起的,所以为了编写出安全 可靠的Web程序,验证表单输入的意义重大。

我们平常编写Web应用主要有两方面的数据验证,一个是在页面端的js验证(目前在这方 面有很多的插件库,比如ValidationJS插件),一个是在服务器端的验证,我们这小节讲解 的是如何在服务器端验证。

必填字段

通过len函数获取表单字段长度来判断字段是否为空:

if len(r.Form["username"][0])==0{
    //为空的处理
}

r.Form对不同类型的表单元素的留空有不同的处理, 对于空文本框、空文本区域以及文件 上传,元素的值为空值,而如果是未选中的复选框和单选按钮,则根本不会在r.Form中产生 相应条目,如果我们用上面例子中的方式去获取数据时程序就会报错。所以我们需要通过 r.Form.Get()来获取值,因为如果字段不存在,通过该方式获取的是空值。但是通过 r.Form.Get()只能获取单个的值,如果是map的值,必须通过上面的方式来获取。

数字

如果我们是判断正整数,那么我们先转化成int类型,然后进行处理

age, err := strconv.Atoi(r.Form.Get("age"))
if err != nil{
    fmt.Fprintf(w, "The format of the input is not correct")
}
if age < 18{
    fmt.Fprintf(w, "Minors are not registered")
}

 

下拉框,复选框,单选框

这种的校验可以预先在服务端创建与客户端选项一致的切片,当客户端提交的时候再与服务端的相比较,决策出输入是否合理。

 

正则表达式

对于一些复杂的字符串可能需要用正则表达式来匹配

if m, _ := regexp.MatchString(`表达式字符串`,
    r.Form.Get("key")); !m {
	//错误处理
}

下面提供几种正则匹配规则:

  • 中文匹配
^[\\x{4e00}-\\x{9fa5}]+$
  • 英文
^[a-zA-Z]+$
  • 邮箱
`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`
  • 手机号码
`^(1[3|4|5|8][0-9]\d{4,8})$`
  • 身份证号码
//验证15位身份证,15位的是全部数字
`^(\d{15})$`
//验证18位身份证,18位前17位为数字,最后一位是校验位,可能为数字或字符X。
`^(\d{17})([0-9]|X)$`

例子

修改下之前的login.ctpl和login函数的代码,测试下我们的表单验证。
login.ctpl:

<html>
<head>
    <title></title>
</head>
<body>
    <form action="http://localhost:9090/login" method="post">
        用户名:<input type="text" name="username">
        年龄:<input type="number" name="age">
        邮箱:<input type="text" name="email">
        <input type="submit" value="按钮">
    </form>
</body>
</html>

login函数

 

func login(w http.ResponseWriter, r *http.Request){
    r.ParseForm() //解析form
    fmt.Println("method: ", r.Method)
    if r.Method == "GET"{
        t, _ := template.ParseFiles("./view/login.ctpl")
        t.Execute(w, nil)
    }else if r.Method == "POST"{
        if len(r.Form["username"][0])==0{
            fmt.Fprintf(w, "username: null or empty \n")
        }
        age, err := strconv.Atoi(r.Form.Get("age"))
        if err != nil{
            fmt.Fprintf(w, "age: The format of the input is not correct \n")
        }
        if age < 18{
            fmt.Fprintf(w, "age: Minors are not registered \n")
        }

        if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`,
            r.Form.Get("email")); !m {
                fmt.Fprintf(w, "email: The format of the input is not correct \n")
        }
    }
}

运行结果:

源码

github 源码地址

转载 Golang Web学习(14)—— 表单处理

标签:Web,13,http,Form,fmt,表单,Golang,login,friend
来源: https://www.cnblogs.com/tianyamoon/p/11131288.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有