Go web编程(七——文本处理)

文本包括字符串、数字、Json、XML等等。
原文作者:Go 技术论坛文档:《Go Web 编程()》
转自链接:https://learnku.com/docs/build-web-application-with-golang/077-summary/3201

XML

<?xml version="1.0" encoding="utf-8"?>
<servers version="1">
    <server>
        <serverName>Shanghai_VPN</serverName>
        <serverIP>127.0.0.1</serverIP>
    </server>
    <server>
        <serverName>Beijing_VPN</serverName>
        <serverIP>127.0.0.2</serverIP>
    </server>
</servers>
  • 解析xml

使用xml包中的Unmarshal函数

func Unmarshal(data []byte,v interface{}) error

data用来接收xml数据流,v把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)    //调用Unmarshal函数
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }

    fmt.Println(v)
}

定义与xml匹配的go语言的Struct类型,然后通过xml.Unmarshal来将xml的数据解析成对应的struct对象。

在上面的代码中可以看到类似于xml:"serverName"这样的内容,被称为struct tag,用来辅助反射的。

调用Unmarshal时首先会读取struct tag,如果没有,那么就会对应字段名,大小写敏感。

  • 输出xml

xml包中提供了Marshal和MarshalIndent两个函数来满足需求。

区别:MarshalIndent会增加前缀和缩进

func Marshal(v interface{})([]byte,error)
func MarshalIndent(v interface{},prefix,indent string)([]byte,error)

例:

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)
}

output:

<?xml version="1.0" encoding="UTF-8"?>
<servers version="1">
<server>
    <serverName>Shanghai_VPN</serverName>
    <serverIP>127.0.0.1</serverIP>
</server>
<server>
    <serverName>Beijing_VPN</serverName>
    <serverIP>127.0.0.2</serverIP>
</server>
</servers>

JSON处理

{
    "servers": [
        {
            "serverName": "Shanghai_VPN", 
            "serverIP": "127.0.0.1"
        }, 
        {
            "serverName": "Beijing_VPN", 
            "serverIP": "127.0.0.2"
        }
    ]
}
  • 解析到struct
func Unmarshal(data []byte,v interface{}) error

解析:

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)
}
  • 解析到interface

不知道被解析的数据的格式时。

bool代表JSON booleans,float64代表JSON numbers,string代表JSON strings,nil代表JSON null。

使用simplejson包:

js, err := simplejson.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

使用JSON包中的Marshal函数来处理,输出JSON格式的数据。

func Marshal(v interface{})([]byte,error)
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))
}

output:

{"Servers":[{"ServerName":"Shanghai_VPN","ServerIP":"127.0.0.1"},{"ServerName":"Beijing_VPN","ServerIP":"127.0.0.2"}]}

想要把开头的大写改为小写就要使用struct tag定义来实现

type Server struct {
    ServerName string `json:"serverName"`
    ServerIP   string `json:"serverIP"`
}

type Serverslice struct {
    Servers []Server `json:"servers"`
}

Marshal只有在转换成功的时候才会返回数据,在转换的过程中需要注意一下几点:

JSON对象只支持string作为key,所以要编码一个map必须是Map[string] (任意类型)。

Channel,complex和function是不能被编码成JSON的

嵌套的数据是不能编码的,不然会让JSON进入死循环

指针在编码的时候回输出指针指向的内容,而空指针会输出null

正则处理

使用regexp标准包。

func Match(pattern string,b []byte)(matched bool,error error)
func MathReader(parttern string,r io.RuneReader)(matched bool,error error)
func MatchString(parttern string,s string)(matched bool,error error)

实现同一个功能,就是判断Parttern是否与输入源匹配,匹配返回true,如果解析错误返回error。

验证IP地址:

func IsIP(ip string) (b bool) {
    if m, _ := regexp.MatchString("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$", ip); !m {
        return false
    }
    return true
}

解析正则表达式的方法:

func Compile(expr string) (*Regexp, error)
func CompilePOSIX(expr string) (*Regexp, error)
func MustCompile(str string) *Regexp
func MustCompilePOSIX(str string) *Regexp

模板

使用template包来进行模板处理。

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语言模板通过{{}}

来包含需要在渲染时被替换的字段,{{.}}表示当前的对象。如果要访问当前字段通过{{.FileName}}。

文件操作

  • 目录操作

OS包

package main
import{
    "fmt"
    "os"
}
func main(){
    os.Mkdir("astaxie",0777)
    os.MkdirAll("astaxie/test1/test2",0777)
    err := os.Remove("astaxie")
    if err != nill {
        fmt.Println(err)
    }
    os.RemoveAll("astaxie")
}
  • 建立文件
func Create(name string)(file *File,err Error)
//根据提供的文件名创建新的文件,返回一个文件对象。默认权限0666
func NewFile(fd uintptr,name string)*File
//根据文件描述符创建相应的文件,返回一个文件对象
  • 打开文件
func Open(name string)(file *File,err Error)
打开一个名称为name的文件,但是是只读方式,内部实现其实调用了OpenFile
func OpenFile(name string,flag int,perm uint32)(file *File,err Error)
  • 写文件函数
func (file *File)Write(b []byte)(n int,err Error)
//写入byte类型的信息到文件
func (file *File)WriteAt(b []byte,off int64)(n int,err Error)
//在指定位置开始写入byte类型的信息
func (file *File)WriteString(s string)(ret int,err Error)
//写入string信息到文件
package main
import(
    "fmt"
    "os"
)
func main(){
    userFile := "astaxie.txt"
    fout,err := os.Create(userFile)
    if err != nil {
        fmt.Println(userFile,err)
        return
    }
    defer fout.Close()
    for i := 0;i<10;i++ {
        fout.WriteString("Just a test!\r\n")
        fout.Write([]byte("Just a test!\r\n"))
    }
}

  • 读文件函数:
func (file *File)Read(b []byte)(n int,err Error)

读取数据到b中

func (file *File)ReatAt(b []byte,off int64)(n int,err Error)

从off开始读取数据到b中

package main
import(
	"fmt"
    "os"
)
func main(){
    userFile := "asatxie.txt"
    fl,err := os.Open(userFile)
    if err != nil {
        fmt.Println(userFile,err)
        return
    }
    defer fl.Close()
    buf := make([]byte,1024)
    for {
        n,_ := fl.Read(buf)
        if 0 == n{
            break
        }
        os.Stdout.Write(buf[:n])
    }
}
  • 删除文件
func Remove(name string)Error

字符串处理

使用strings包。

func Contains(s,substr string)bool
//判断字符串s手否包含substr,返回bool值。
func Join(a []string,sep string)string
//字符串连接,把slice a通过sep链接起来。
func Index(s,sep string)int
//在字符串s查找sep所在的位置,返回位置值,找不到返回-1
func Repeat(s string,cout int)string
//重复s字符串count次,最后返回重复的字符串
func Replace(s,old,new string,n int)string
//在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换
func Split(s,sep string)[]string
//把s字符串按照sep分割,返回slice
func Trim(s string,cutset string)string
//在s字符串的头部和尾部去除cutset指定的字符串
func Fields(s string)[]string
//去除s字符串的空格符,并且按照空格分割返回slice

  • 字符串转换

字符串转化的函数在strconv中。

Append

str:=make([]byte,0,100)
str = strconv.AppendInt(str,4567,10)

Format包中函数把其他类型转换为字符串

a := strconv.FormatBool(false)

Parse系列函数把字符串转换为其他类型

a,err := strconv.ParseBool("false")
posted @ 2021-05-16 16:25  Gumi-21  阅读(106)  评论(0)    收藏  举报