goweb-文本处理
文本处理
web开发中对于文本处理是非常重要的一部分,我们往往需要对输出或者输入的内容进行处理,这里的文本包括字符串、数字、json、xml等等。go语言作为一门高性能的语言,对这些文本的处理都有官方的标准库来支持。而且在你使用中你会发现go标准库的一些设计相当的巧妙,而且对于使用者来说也很方便就能处理这些文本。
xml处理
xml作为一种数据交换和信息传递的格式已经十分普及。而随着web服务日益广泛的应用,现在xml在日常的开发工作中也扮演了愈发重要的角色
解析xml
如何解析如上这个xml文件呢? 我们可以通过xml包的unmarshal函数来达到我们的目的
func unmarshal(data []byte, v interface{}) error
data接收的是xml数据流,v是需要输出的结构,定义为interface,也就是可以把xml转换为任意的格式。我们这里主要介绍struct的转换,因为struct和xml都有类似树结构的特征。
package main import ( "encoding/xml" "fmt" "io/ioutil" "os" ) type recurlyservers struct { xmlname xml.name `xml:"servers"` version string `xml:"version,attr"` svs []server `xml:"server"` description string `xml:",innerxml"` } type server struct { xmlname xml.name `xml:"server"` servername string `xml:"servername"` serverip string `xml:"serverip"` } func main() { file, err := os.open("servers.xml") // for read access. if err != nil { fmt.printf("error: %v", err) return } defer file.close() data, err := ioutil.readall(file) if err != nil { fmt.printf("error: %v", err) return } v := recurlyservers{} err = xml.unmarshal(data, &v) if err != nil { fmt.printf("error: %v", err) return } fmt.println(v) }
输出xml
假若我们不是要解析如上所示的xml文件,而是生成它,那么在go语言中又该如何实现呢? xml包中提供了marshal和marshalindent两个函数,来满足我们的需求。这两个函数主要的区别是第二个函数会增加前缀和缩进,函数的定义如下所示:
func marshal(v interface{}) ([]byte, error)
func marshalindent(v interface{}, prefix, indent string) ([]byte, error)
两个函数第一个参数是用来生成xml的结构定义类型数据,都是返回生成的xml数据流。
package main import ( "encoding/xml" "fmt" "os" ) type servers struct { xmlname xml.name `xml:"servers"` version string `xml:"version,attr"` svs []server `xml:"server"` } type server struct { servername string `xml:"servername"` serverip string `xml:"serverip"` } func main() { v := &servers{version: "1"} v.svs = append(v.svs, server{"shanghai_vpn", "127.0.0.1"}) v.svs = append(v.svs, server{"beijing_vpn", "127.0.0.2"}) output, err := xml.marshalindent(v, " ", " ") if err != nil { fmt.printf("error: %v\n", err) } os.stdout.write([]byte(xml.header)) os.stdout.write(output) }
上面我们介绍了如何使用go语言的xml包来编/解码xml文件,重要的一点是对xml的所有操作都是通过struct tag来实现的,所以学会对struct tag的运用变得非常重要
json处理
json(javascript object notation)是一种轻量级的数据交换语言,以文字为基础,具有自我描述性且易于让人阅读。尽管json是javascript的一个子集,但json是独立于语言的文本格式,并且采用了类似于c语言家族的一些习惯。json与xml最大的不同在于xml是一个完整的标记语言,而json不是。json由于比xml更小、更快,更易解析,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。目前我们看到很多的开放平台,基本上都是采用了json作为他们的数据交互的接口。既然json在web开发中如此重要,那么go语言对json支持的怎么样呢?go语言的标准库已经非常好的支持了json,可以很容易的对json数据进行编、解码的工作。
解析json
package main import ( "encoding/json" "fmt" ) type server struct { servername string serverip string } type serverslice struct { servers []server } func main() { var s serverslice str := `{"servers":[{"servername":"shanghai_vpn","serverip":"127.0.0.1"},{"servername":"beijing_vpn","serverip":"127.0.0.2"}]}` json.unmarshal([]byte(str), &s) fmt.println(s) }
上面这个是官方提供的解决方案,其实很多时候我们通过类型断言,操作起来不是很方便,目前bitly公司开源了一个叫做simplejson的包,在处理未知结构体的json时相当方便,详细例子如下所示:
js, err := newjson([]byte(`{ "test": { "array": [1, "2", 3], "int": 10, "float": 5.150, "bignum": 9223372036854775807, "string": "simplejson", "bool": true } }`)) arr, _ := js.get("test").get("array").array() i, _ := js.get("test").get("int").int() ms := js.get("test").get("string").muststring()
生成json
package main import ( "encoding/json" "fmt" ) type server struct { servername string serverip string } type serverslice struct { servers []server } func main() { var s serverslice s.servers = append(s.servers, server{servername: "shanghai_vpn", serverip: "127.0.0.1"}) s.servers = append(s.servers, server{servername: "beijing_vpn", serverip: "127.0.0.2"}) b, err := json.marshal(s) if err != nil { fmt.println("json err:", err) } fmt.println(string(b)) }
正则处理
正则表达式是一种进行模式匹配和文本操纵的复杂而又强大的工具。虽然正则表达式比纯粹的文本匹配效率低,但是它却更灵活。按照它的语法规则,随需构造出的匹配模式就能够从原始文本中筛选出几乎任何你想要得到的字符组合。如果你在web开发中需要从一些文本数据源中获取数据,那么你只需要按照它的语法规则,随需构造出正确的模式字符串就能够从原数据源提取出有意义的文本信息。
go语言通过regexp标准包为正则表达式提供了官方支持,如果你已经使用过其他编程语言提供的正则相关功能,那么你应该对go语言版本的不会太陌生,但是它们之间也有一些小的差异,因为go实现的是re2标准,除了\c,详细的语法描述参考:http://code.google.com/p/re2/wiki/syntax
其实字符串处理我们可以使用strings包来进行搜索(contains、index)、替换(replace)和解析(split、join)等操作,但是这些都是简单的字符串操作,他们的搜索都是大小写敏感,而且固定的字符串,如果我们需要匹配可变的那种就没办法实现了,当然如果strings包能解决你的问题,那么就尽量使用它来解决。因为他们足够简单、而且性能和可读性都会比正则好。
通过正则判断是否匹配
regexp包中含有三个函数用来判断是否匹配,如果匹配返回true,否则返回false
func match(pattern string, b []byte) (matched bool, error error) func matchreader(pattern string, r io.runereader) (matched bool, error error) func matchstring(pattern string, s string) (matched bool, error error)
上面的三个函数实现了同一个功能,就是判断pattern是否和输入源匹配,匹配的话就返回true,如果解析正则出错则返回error。三个函数的输入源分别是byte slice、runereader和string。
这把整个regexp包都讲了讲,讲的还挺细!!!
模板处理
什么是模板?
你一定听说过一种叫做mvc的设计模式,model处理数据,view展现结果,controller控制用户的请求,至于view层的处理,在很多动态语言里面都是通过在静态html中插入动态语言生成的数据,例如jsp中通过插入<%=....=%>,php中通过插入来实现的。
web应用反馈给客户端的信息中的大部分内容是静态的,不变的,而另外少部分是根据用户的请求来动态生成的,例如要显示用户的访问记录列表。用户之间只有记录数据是不同的,而列表的样式则是固定的,此时采用模板可以复用很多静态代码。
go模板使用
在go语言中,我们使用template包来进行模板处理,使用类似parse、parsefile、execute等方法从文件或者字符串加载模板,然后执行类似上面图片展示的模板的merge操作。请看下面的例子:
func handler(w http.responsewriter, r *http.request) { t := template.new("some template") //创建一个模板 t, _ = t.parsefiles("tmpl/welcome.html") //解析模板文件 user := getuser() //获取当前用户信息 t.execute(w, user) //执行模板的merger操作 }
通过上面的例子我们可以看到go语言的模板操作非常的简单方便,和其他语言的模板处理类似,都是先获取数据,然后渲染数据。
通过模板技术的应用,我们可以完成mvc模式中v的处理
文件操作
在任何计算机设备中,文件是都是必须的对象,而在web编程中,文件的操作一直是web程序员经常遇到的问题,文件操作在web应用中是必须的,非常有用的,我们经常遇到生成文件目录,文件(夹)编辑等操作,这本书把go中的这些操作做一详细总结并实例示范如何使用。
字符串处理
字符串在我们平常的web开发中经常用到,包括用户的输入,数据库读取的数据等,我们经常需要对字符串进行分割、连接、转换等操作,这一小节将通过go标准库中的strings和strconv两个包中的函数来讲解如何进行有效快速的操作。
string主要是对字符串进行操作,strconv主要是进行字符串与其他数据类型的转换。
这一章介绍了一些文本处理的工具,包括xml、json、正则和模板技术,xml和json是数据交互的工具,通过xml和json你可以表达各种含义,通过正则你可以处理文本(搜索、替换、截取),通过模板技术你可以展现这些数据给用户。这些都是你开发web应用过程中需要用到的技术,通过这个小节的介绍你能够了解如何处理文本、展现文本。
上一篇: Jaeger容器化部署
下一篇: goweb-web服务