文本处理 3.21
本文基本摘录至https://learnku.com/docs/build-web-application-with-golang/073-regular-processing/3197,仅供学习,如果有需要学习web的同学可以看这个,不懂的再来看我的,我的仅作补充
文本处理是什么?
通常情况下,我们作为设置服务器的,需要对客户端发送过来的文本文件进行解析/对数据进行验证(验证码)/对关键词进行提取(搜索引擎)/除去其他无关信息/对一些信息进行安全处理(扫黄?)/接收到的信息是否符合业务逻辑
正则判断
我想既然我不会设计正则表达式,那么我想让chatgpt帮我实现
嗯,我只是想一下
但其实还是要会一点点东西
不然那个机器人打出来我都看不懂
还是了解一下正则表达式的基本符号吧(可以结合例子来看,看那个太枯燥了)
-
匹配单个字符:
.
:匹配除换行符之外的任意单个字符。[abc]
:匹配字符集合中的任意一个字符,例如匹配a、b或c。
-
量词:
*
:匹配前面的字符零次或多次。+
:匹配前面的字符一次或多次。?
:匹配前面的字符零次或一次。{n}
:匹配前面的字符恰好n次。{n,}
:匹配前面的字符至少n次。{n,m}
:匹配前面的字符至少n次但不超过m次。
-
位置锚点:
^
:匹配输入字符串的开始位置。$
:匹配输入字符串的结束位置。
-
特殊字符转义:
\
:用于转义特殊字符,使其成为普通字符。例如,\.
匹配句点字符.
。
-
字符类别简写:
\d
:匹配数字字符,相当于[0-9]
。\w
:匹配单词字符(字母、数字、下划线),相当于[a-zA-Z0-9_]
。\s
:匹配空白字符(空格、制表符、换行符等)。\D
、\W
、\S
:分别是\d
、\w
、\s
的反义。
-
分组和捕获:
()
:用于创建捕获组,将匹配的内容分组。(?:)
:非捕获分组,不会存储匹配结果。
-
选择符:
|
:用于在多个模式之间选择匹配其中之一。
-
反义:
[^]
:匹配除括号中字符之外的任意一个字符。
-
其他常用语法:
*?
、+?
、??
:非贪婪匹配,尽可能少地匹配字符。\b
、\B
:单词边界和非单词边界。
常见的正则表达式:
1.匹配邮箱地址:
\w+@\w+\.\w+
\w+是用来匹配单个或多个字母,数字或下划线,也就是说
\w+
可以匹配字符串"19366566265safa_saf"。\w+
匹配一个或多个字母、数字或下划线字符,因此它能够匹配字符串中的数字、字母和下划线部分。
@用来匹配@符号
注意:正则表达式是一个整体,+不是用来连接的,而只是用来表明可以接收单个或多个(在原本的含义上)
2.匹配URL:
https?://\w+(\.\w+)+
?是用来表示匹配前面的字符(单个)零次或者一次,也就是协议只有两种https/http
通常一个域名
https://chat.openai.com/c/f378fb54-707b-4412-8123-540bb47735ad
https?://\w+(\.\w+)+(/.*)?
需要修改成这样
(/.*)?注意?之前是有个括号的,.表示匹配除了换行符以外的字符,*****表示多次
类似于这样子他会有很多个
3.匹配日期
\d{4}-\d{2}-\d{2}
我们可以观察到我们的日期的格式是
20040819
这个就不多解释了
4.匹配HTML标签
<[^>]+>
两边的< >是用来匹配<>这个不多说
[^>]是用来匹配除了>的的任何字符,然后后面跟着一个+说明可以匹配很多
5.匹配手机号码:
regexCopy code
1[3-9]\d{9}
这个正则表达式匹配中国大陆手机号码,其中1
匹配手机号码的开头,[3-9]
匹配第二位数字(3至9中的一个),\d{9}
匹配后面的9位数字。
回归正题,我们来看一下go语言中regexp包,这个是和匹配正则表达式相关的
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)
/*
三个输入源分别是byte slice,RuneReader,string
patter就是输入源
*/
下面我们来举个例子,
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
}
/Pv4地址的范围是0.0.0.0到255.255.255.255 $表示结束
\.这里查了chatgpt,就是说因为.本身表示的是匹配除了.之外的字符,但是我偏偏就需要匹配. 但是\也是一个特殊字符,他不能单独使用,例如\n对吧
所以我们需要使用\/
这里我是在goLand上面进行了一个实验的,大家可以做一下,加强对这个函数的理解,代码不用全部打
func main() {if len(os.Args) == 1 {fmt.Println("Usage: regexp [string]")os.Exit(1)} else if m, _ := regexp.MatchString("^[0-9]+$", os.Args[1]); m {fmt.Println("数字")} else {fmt.Println("不是数字")}
}
我一开始也没有弄懂os.Args什么意思,我是个小菜鸡
chatgpt回答:
os
包主要用于处理命令行参数和退出程序。
os.Args
是一个字符串切片,其中存储了命令行参数。os.Args[0]
存储了程序的名称,而后续的元素存储了传递给程序的命令行参数。
这个要做实验的话需要用到我们的终端(也就是cmd),不能直接使用run
通过正则来获取内容
package mainimport ("fmt""io/ioutil""net/http""regexp""strings"
)func main() {resp, err := http.Get("http://www.baidu.com")if err != nil {fmt.Println("http get error.")}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println("http read error")return}src := string(body)// 将 HTML 标签全转换成小写re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")src = re.ReplaceAllStringFunc(src, strings.ToLower)// 去除 STYLEre, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")src = re.ReplaceAllString(src, "")// 去除 SCRIPTre, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")src = re.ReplaceAllString(src, "")// 去除所有尖括号内的 HTML 代码,并换成换行符re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")src = re.ReplaceAllString(src, "\n")// 去除连续的换行符re, _ = regexp.Compile("\\s{2,}")src = re.ReplaceAllString(src, "\n")fmt.Println(strings.TrimSpace(src))
}
这个大家可以直接复制这段代码然后直接运行
大概意思就是将网页中的HTML文件转换成我们想要得到的信息
然后他会有这么几个方法:
func Compile(expr string) (*Regexp, error)
func CompilePOSIX(expr string) (*Regexp, error)
func MustCompile(str string) *Regexp
func MustCompilePOSIX(str string) *Regexp
前面我们都是新建一个Regexp,然后还可以辅助操作我们得到的字符串
func (re *Regexp) Find(b []byte) []byte
func (re *Regexp) FindAll(b []byte, n int) [][]byte
func (re *Regexp) FindAllIndex(b []byte, n int) [][]int
func (re *Regexp) FindAllString(s string, n int) []string
func (re *Regexp) FindAllStringIndex(s string, n int) [][]int
func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string
func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int
func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int
func (re *Regexp) FindIndex(b []byte) (loc []int)
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int)
func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int
func (re *Regexp) FindString(s string) string
func (re *Regexp) FindStringIndex(s string) (loc []int)
func (re *Regexp) FindStringSubmatch(s string) []string
func (re *Regexp) FindStringSubmatchIndex(s string) []int
func (re *Regexp) FindSubmatch(b []byte) [][]byte
func (re *Regexp) FindSubmatchIndex(b []byte) []int
简化之后,主要就是使用这几个方法
func (re *Regexp) Find(b []byte) []byte
func (re *Regexp) FindAll(b []byte, n int) [][]byte
func (re *Regexp) FindAllIndex(b []byte, n int) [][]int
func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int
func (re *Regexp) FindIndex(b []byte) (loc []int)
func (re *Regexp) FindSubmatch(b []byte) [][]byte
func (re *Regexp) FindSubmatchIndex(b []byte) []int
然后下面的这个实验部分我还是老老实实的打了的,毕竟要了解一下
package mainimport ("fmt""regexp"
)func main() {a := "I am learning Go language"re, _ := regexp.Compile("[a-z]{2,4}")/*找到第一个小写字母 2-4个*/one := re.Find([]byte(a))fmt.Println("Find:", string(one))all := re.FindAll([]byte(a), -1)//FindAll返回的是当前字符串UTF表中的序号fmt.Println("FindAll:", all)// 查找符合条件的 index 位置, 开始位置和结束位置index := re.FindIndex([]byte(a))fmt.Println("FindIndex", index)// 查找符合条件的所有的 index 位置,n 同上allindex := re.FindAllIndex([]byte(a), -1)fmt.Println("FindAllIndex", allindex)re2, _ := regexp.Compile("am(.*)lang(.*)")// 查找 Submatch, 返回数组,第一个元素是匹配的全部元素,第二个元素是第一个 () 里面的,第三个是第二个 () 里面的// 下面的输出第一个元素是 "am learning Go language"// 第二个元素是 " learning Go ",注意包含空格的输出// 第三个元素是 "uage"submatch := re2.FindSubmatch([]byte(a))fmt.Println("FindSubmatch", submatch)for _, v := range submatch {fmt.Println(string(v))}// 定义和上面的 FindIndex 一样submatchindex := re2.FindSubmatchIndex([]byte(a))fmt.Println(submatchindex)// FindAllSubmatch, 查找所有符合条件的子匹配submatchall := re2.FindAllSubmatch([]byte(a), -1)fmt.Println(submatchall)// FindAllSubmatchIndex, 查找所有字匹配的 indexsubmatchallindex := re2.FindAllSubmatchIndex([]byte(a), -1)fmt.Println(submatchallindex)}
这个后面的我没有很弄懂,但是我感觉我现在弄懂了也没有什么意义
然后他解释一个Expand
func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte
func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte
package mainimport ("fmt""regexp"
)func main() {src := []byte(`call hello alicehello bobcall hello eve`)pat := regexp.MustCompile(`(?m)(call)\s+(?P<cmd>\w+)\s+(?P<arg>.+)\s*$`)/*这里创建了一个字符串(正则表达式),匹配类似函数调用的字符串*/res := []byte{}//用来存储最终的替换结果for _, s := range pat.FindAllSubmatchIndex(src, -1) {res = pat.Expand(res, []byte("$cmd('$arg')\n"), src, s)}//按照pat的格式对src进行格式替换fmt.Println(string(res))}
这个我就迷迷糊糊的过了
JSON处理
总有一天,你会知道你学的这个其实是有用的,知识是不断建立起来的,你现在是不会知道有用,但未来会知道的
会有一个JSON文件需要我们去处理,提取json中的相关信息,通过方法
我们会有两种解决方案
一种是已知JSON数据 的结构前提下
package mainimport ("encoding/json""fmt"
)type Server struct {ServerName stringServerIP string
}
/*
如果说你不想要ServerName可以将开头字母小写,这样的画就不会访问得到
*/type Serverslice struct {Servers []Server
}func main() {var s Serverslicestr := `{"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)
}
接着不知道Json的数据结构,这样我们上面的ServerName 和 ServerIP是没有任何用的
但是我们的interface可以接受任意类型的
识记:
JSON包中采用map[string]interface{} 和 []interface{} 结构来存储任意的JSON对形象和数组
- bool 代表 JSON booleans,
- float64 代表 JSON numbers,
- string 代表 JSON strings,
- nil 代表 JSON null.
package mainimport ("encoding/json""fmt"
)type Server struct {ServerName stringServerIP string
}type Serverslice struct {Servers []Server
}func main() {b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)var f interface{}err := json.Unmarshal(b, &f)if err != nil {}m := f.(map[string]interface{})/*这里我疑惑,这个不是知道它的数据类型了吗*/for k, v := range m {switch vv := v.(type) {case string:fmt.Println(k, "is string", vv)case int:fmt.Println(k, "is int", vv)case float64:fmt.Println(k, "is float64", vv)case []interface{}:fmt.Println(k, "is an array:")for i, u := range vv {fmt.Println(i, u)}default:fmt.Println(k, "is of a type I don't know how to handle")}}
}
这样子不是很方便,所以我们使用bitly公司开发的一个simplejson包
package mainimport "github.com/bitly/go-simplejson"func main() {js, err := simplejson.NewJson([]byte(`{"test": {"array": [1, "2", 3],"int": 10,"float": 5.150,"bignum": 9223372036854775807,"string": "simplejson","bool": true}
}`))
/*
实际上,我们假设有一个test的这样一个json文件
然后key他是我们的文件名,后面的就是我们要获取的数组 int 或者string类型的参数
*/arr, _ := js.Get("test").Get("array").Array()i, _ := js.Get("test").Get("int").Int()ms := js.Get("test").Get("string").MustString()
}
生成JSON
JSON包可以通过Marshal函数来处理,函数
func Marshal(v interface{}) ([]byte, error)
/*
v就是我们要转换成json的源文件,然后我们要转化成[]byte类型的格式
因为json文件是byte类型的文件
*/
package mainimport ("encoding/json""fmt"
)type Server struct {ServerName stringServerIP string
}type Serverslice struct {Servers []Server
}func main() {var s Serverslices.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))
}
模板处理
这个模板的意思解析一下就是:很多时候,在用户的界面我们只需要修改它的某个项目,eg:姓名,电话,其他的样式,图片是一样的
Go模板使用
在Go语言中,我们使用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) //执行模板的merge操作
}
步骤:先获取数据,然后渲染数据
在下面的实例中:
我们将:
使用 Parse 代替 ParseFiles,因为 Parse 可以直接测试一个字符串,而不需要额外的文件
不使用 handler 来写演示代码,而是每个测试一个 main,方便测试
使用 os.Stdout 代替 http.ResponseWriter,因为 os.Stdout 实现了 io.Writer 接口
一个模板都是应用在go的一个对象中,那么我们如何将对象的字段插入到模板中呢?
字段操作
Go语言的模板通过{{}}
来包含需要在渲染时被替换的字段
{{.}}
表示当前的对象,和this相似
{{.FieldName}}
用来访问当前对象的FieldName的字段,但是这个访问字段在struct中必须是要大写的,否则在渲染中会报错
package mainimport ("html/template""os"
)type Person struct {UserName string
}func main() {t := template.New("fieldname example")t, _ = t.Parse("hello {{.UserName}}")//这个就是模板p := Person{UserName: "AStaxie"}t.Execute(os.Stdout, p)
}
我们在字段中重新添加一个email,虽然说最后不会输出email
当然也不会报错
package mainimport ("html/template""os"
)type Person struct {UserName stringemail string
}func main() {t := template.New("fieldname example")t, _ = t.Parse("hello {{.UserName}}! {{.email}}") //这个就是模板文件p := Person{UserName: "AStaxie"}t.Execute(os.Stdout, p)
}
输出嵌套字段内容
如果字段里面有对象,该怎么输出
package mainimport ("html/template""os"
)type Friend struct {Fname string
}type Person struct {UserName stringEmails []stringFriends []*Friend
}func main() {f1 := Friend{Fname: "minux.ma"}f2 := Friend{Fname: "xushiwei"}t := template.New("fieldname example")t.Parse(`hello{{.UserName}}!
{{range .Emails}}
an email {{.}}
{{end}}
{{with .Friends}}
{{range .}}
my friend name is {{.Fname}}
{{end}}
{{end}}`)p := Person{UserName: "Astaxie",Emails: []string{"astaxie@beego.me", "astaxie@gmail.com"},Friends: []*Friend{&f1, &f2}}t.Execute(os.Stdout, p)
}
这段代码我是着实没有看懂什么,作者也没有解释
我们可以发现Person结构体中是有Friends对象的,对于这种我们可以使用with来牵扯出这个对象 with .Friends
注意一下这里的点是附属关系的表现
然后我们 使用{{range.}}
这个就是遍历我们的Friends中的全部集合元素
然后在之后访问的时候
假设你想得到的是FieldName这个属性
{{.FieldName}}
通过 {{range .}}
结构迭代集合时,你可以访问到对象中的所有字段和方法,只需要在 .
后面加上你想访问的字段名或方法名即可。
{{range}}
和 {{with}}
结构都是带有起始标签和结束标签的控制结构。这些结构的起始标签是 {{range .}}
和 {{with .}}
,而对应的结束标签是 {{end}}
。
条件处理
对于一个模板,我们可以对输入的信息进行判断,然后切换不同的模板
pipeline 是一种将多个命令和操作符连接起来的方式,用于对数据进行处理或转换
在模板语法中,我们可以使用 range
结构迭代一个切片,并使用 {{.}}
来获取当前迭代元素的值。而 {{.}}
表示当前迭代元素的值,就是一个 pipeline,它将当前元素传递给下一个命令或操作符。
package mainimport ("os""text/template"
)func main() {tEmpty := template.New("template test")tEmpty = template.Must(tEmpty.Parse("空 pipeline if demo: {{if ``}} 不会输出. {{end}}\n"))// {{if ``}}这个是如果为空的意思tEmpty.Execute(os.Stdout, nil)tWithValue := template.New("template test")tWithValue = template.Must(tWithValue.Parse("不为空的 pipeline if demo: {{if `anything`}} 我有内容,我会输出. {{end}}\n"))//{{if `anything`}}这个是如果不为空tWithValue.Execute(os.Stdout, nil)tIfElse := template.New("template test")tIfElse = template.Must(tIfElse.Parse("if-else demo: {{if `anything`}} if部分 {{else}} else部分.{{end}}\n"))tIfElse.Execute(os.Stdout, nil)
}
模板变量
我们使用{{variable := pipeline}}
语法来声明一个模板变量。将在当前作用域内创建一个局部变量,该变量的生命周期限定在该作用域内,通常是在{{end}}结束标价之前
package mainimport ("os""text/template"
)func main() {// 定义模板tmpl := `{{with $x := "output"}}{{$x | printf "%q"}}{{end}}`//将字符串output格式化为带引号的字符串// 解析模板t := template.Must(template.New("tmpl").Parse(tmpl))// 执行模板并输出结果err := t.Execute(os.Stdout, nil)if err != nil {panic(err)}
}
我真的感觉好大的阻力看这个东西,有种欲哭无泪的感觉
直接到文件操作吧
文件操作
目录操作
就是我们可以创建或者删除目录的一些函数
func Mkdir(name string, perm FileMode) error创建名称为 name 的目录,权限设置是 perm,例如 0777
说一下权限设置是什么意思
权限是由三个数字组成的,每个数字表示对应用户组(所有者,群组,其他用户)的权限,采用8进制,每个数字分别表示读(r),写(w),执行(x)权限
r:表示能读取文件内容或者查看目录中的文件列表
w:表示能写入或修改文件内容,对目录而言表示能够在其中创建,删除或重命名文件
x:表示能够执行文件或者进入目录在权限设置中,八进制的第一个数字表示所有者的权限,第二个数字表示群组的权限,第三个数字表示其他用户的权限。他们的位置分别是4,2,1.
4+2+1 = 7func MkdirAll(path string, perm FileMode) error根据 path 创建多级子目录,例如 astaxie/test1/test2。func Remove(name string) error删除名称为 name 的目录,当目录下有文件或者其他目录时会出错func RemoveAll(path string) error根据 path 删除多级子目录,如果 path 是单个名称,那么该目录下的子目录全部删除。
文件操作
新建文件可以通过如下两个方法
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)
打开名称为 name 的文件,flag 是打开的方式,只读、读写等,perm 是权限
写文件
写文件函数:
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 mainimport ("fmt""os"
)func main() {userFile := "test.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)//读取数据到buf中if n == 0 {break}os.Stdout.Write(buf[:n])}
}
字符串处理
我们通常提取的数据都是字符串,但是如何对这些字符串进行分割连接呢
字符串操作
package mainimport ("fmt""strings"
)func main() {/*func Contains(s,substr string)bool字符串s中是否包含substr,返回bool值*/fmt.Println(strings.Contains("seafood", "foo"))fmt.Println(strings.Contains("seafood", "bar"))fmt.Println(strings.Contains("seafood", ""))fmt.Println(strings.Contains("", ""))// Output:// true// false// true// true
}
s := []string{"lxy", "zcx", "xzc"}fmt.Println(strings.Join(s, " and "))
/*
func Join(a []string,sep string)string
字符串链接,把slice a 通过sep连接起来
*/
package mainimport ("fmt""strings"
)func main() {/*func Contains(s,substr string)bool字符串s中是否包含substr,返回bool值*/fmt.Println(strings.Contains("seafood", "foo"))fmt.Println(strings.Contains("seafood", "bar"))fmt.Println(strings.Contains("seafood", ""))fmt.Println(strings.Contains("", ""))// Output:// true// false// true// trues := []string{"lxy", "zcx", "xzc"}fmt.Println(strings.Join(s, " and "))/*func index(s,sep string)int在字符串s中查找sep所在的位置,返回位置值,找不到返回-1*/fmt.Println(strings.Index("chicken", "ken"))fmt.Println(strings.Index("chicken", "dmr"))/*func Repeat(s string,count int) string重复s字符串count次,最后返回重复的字符串*/fmt.Println("ba" + strings.Repeat("laa", 2))/*func Replace(s,old,new string,n int)string在s字符串,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换*/fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))fmt.Println(strings.Replace("hello hello hello", "el", "56", -1))/*func Split(s,sep string)[]string把s字符串按照sep分割,返回slice*/fmt.Printf("%q\n", strings.Split("a,b,c", ","))fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))/*%q是一种格式化字符串的标记也就是会转义像"\n"不会变成换行符*//*func Trim(s string,cutset string) string在s字符串的头部和尾部取出cutset指定的字符串*/fmt.Printf("[%q]", strings.Trim("!!! action !!!", "!"))/*func Field(s string)[]string去除s字符串的空格符,并且按照空格分割返回slice*/fmt.Printf("Fields are: %q", strings.Fields(" foo bar baz "))
}
字符串转换
将整数转化为字符串,并且添加到现有的字节数组中
package mainimport ("fmt""strconv"
)func main() {str := make([]byte, 0, 100)str = strconv.AppendInt(str, 4567, 10)str = strconv.AppendBool(str, false)str = strconv.AppendQuote(str, "abcdefg")str = strconv.AppendQuoteRune(str, '单')fmt.Println(string(str))
}
- Format系列函数把其他类型的转换为字符串
package mainimport ("fmt""strconv"
)func main() {a := strconv.FormatBool(false)b := strconv.FormatFloat(123.23, 'g', 12, 64)c := strconv.FormatInt(1234, 10)d := strconv.FormatUint(12345, 10)e := strconv.Itoa(1023)fmt.Println(a, b, c, d, e)
}
- Parse系列函数把字符串转换为其他类型
package mainimport ("fmt""strconv"
)
func checkError(e error){if e != nil{fmt.Println(e)}
}
func main() {a, err := strconv.ParseBool("false")checkError(err)b, err := strconv.ParseFloat("123.23", 64)checkError(err)c, err := strconv.ParseInt("1234", 10, 64)checkError(err)d, err := strconv.ParseUint("12345", 10, 64)checkError(err)e, err := strconv.Atoi("1023")checkError(err)fmt.Println(a, b, c, d, e)
}
这前面三个看看就行