文本处理(有关go web方面)

文本处理 3.21

本文基本摘录至https://learnku.com/docs/build-web-application-with-golang/073-regular-processing/3197,仅供学习,如果有需要学习web的同学可以看这个,不懂的再来看我的,我的仅作补充

文本处理是什么?

通常情况下,我们作为设置服务器的,需要对客户端发送过来的文本文件进行解析/对数据进行验证(验证码)/对关键词进行提取(搜索引擎)/除去其他无关信息/对一些信息进行安全处理(扫黄?)/接收到的信息是否符合业务逻辑

正则判断

我想既然我不会设计正则表达式,那么我想让chatgpt帮我实现

嗯,我只是想一下

但其实还是要会一点点东西

不然那个机器人打出来我都看不懂

还是了解一下正则表达式的基本符号吧(可以结合例子来看,看那个太枯燥了)

  1. 匹配单个字符

    • .:匹配除换行符之外的任意单个字符。
    • [abc]:匹配字符集合中的任意一个字符,例如匹配a、b或c。
  2. 量词

    • *:匹配前面的字符零次或多次。
    • +:匹配前面的字符一次或多次。
    • ?:匹配前面的字符零次或一次。
    • {n}:匹配前面的字符恰好n次。
    • {n,}:匹配前面的字符至少n次。
    • {n,m}:匹配前面的字符至少n次但不超过m次。
  3. 位置锚点

    • ^:匹配输入字符串的开始位置。
    • $:匹配输入字符串的结束位置。
  4. 特殊字符转义

    • \:用于转义特殊字符,使其成为普通字符。例如,\.匹配句点字符.
  5. 字符类别简写

    • \d:匹配数字字符,相当于[0-9]
    • \w:匹配单词字符(字母、数字、下划线),相当于[a-zA-Z0-9_]
    • \s:匹配空白字符(空格、制表符、换行符等)。
    • \D\W\S:分别是\d\w\s的反义。
  6. 分组和捕获

    • ():用于创建捕获组,将匹配的内容分组。
    • (?:):非捕获分组,不会存储匹配结果。
  7. 选择符

    • |:用于在多个模式之间选择匹配其中之一。
  8. 反义

    • [^]:匹配除括号中字符之外的任意一个字符。
  9. 其他常用语法

    • *?+???:非贪婪匹配,尽可能少地匹配字符。
    • \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))
}

模板处理

img

这个模板的意思解析一下就是:很多时候,在用户的界面我们只需要修改它的某个项目,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:表示能够执行文件或者进入目录在权限设置中,八进制的第一个数字表示所有者的权限,第二个数字表示群组的权限,第三个数字表示其他用户的权限。他们的位置分别是421.
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)
}

这前面三个看看就行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/282844.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于CSS3制作专属可自由旋转的立方体

一、代码区域 1.1 css3代码区域 <style>* {padding: 0;margin: 0;list-style: none;}/* 1) 定义动画 */keyframes loop {0% {transform: rotateX(348deg) rotateY(67deg) rotateZ(95deg);}50% {transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);}100% {transform:…

论文阅读-MIPD:一种用于分布式深度神经网络训练的自适应梯度稀疏化框架

摘要—基于参数服务器架构的异步训练广泛应用于大规模数据集和深度神经网络模型的扩展训练。在大规模分布式深度学习系统中&#xff0c;通信一直被认为是主要瓶颈。最近的研究尝试通过梯度稀疏化和量化方法来减少通信流量。我们发现前期研究存在三个限制。首先&#xff0c;他们…

基于python+vue网络相册设计与实现flask-django-nodejs-php

网络相册设计与实现的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&#xff0…

蓝桥杯2021年第十三届省赛真题-卡片

一、题目 卡片 小蓝有很多数字卡片&#xff0c;每张卡片上都是数字 0 到 9。 小蓝准备用这些卡片来拼一些数&#xff0c;他想从 1 开始拼出正整数&#xff0c;每拼一个&#xff0c; 就保存起来&#xff0c;卡片就不能用来拼其它数了。 小蓝想知道自己能从 1 拼到多少。 例如&am…

Cookie和Session登录注册案例

文章目录 一、需求说明![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f29467ed6b7f4de7a568004ad50de591.png)二、用户登录1、Dao层代码2、Service层代码3、Web层代码 三、记住用户四、用户注册五、展示验证码 一、需求说明 二、用户登录 1、Dao层代码 UserMapp…

双指针(滑动窗口)-算法刷题

一.移动零 算法思想 &#xff1a; 设置两个指针left,right&#xff0c;将数组分为三块[0,left]为不为0的元素&#xff0c;[left1,right-1]为0元素&#xff0c;[right,num.size()-1]为未扫描的区域&#xff0c;判断right位置&#xff0c;不为0元素则与left1位置元素交换,left和r…

使用jupyter-Python进行模拟股票分析

tushare财经数据接口包 pip install tushare作用&#xff1a;提供相关指定的财经数据 需求&#xff1a;股票分析 使用tushare包获取某股票的历史行情数据 输出该股票所有收盘比开盘上涨3%以上的日期 输出该股票所有开盘比前日收盘跌幅超过2%的日期 假如我从2015年1月1日开…

人像抠图HumanSeg——基于大规模电话会议视频数据集的连接感知人像分割

前言 人像抠图将图像中的人物与背景进行像素级别的区分的技术。通过人像分割&#xff0c;可以实现诸如背景虚化、弹幕穿人等各种有趣的功能&#xff0c;为视频通话和影音观看提供更加优质和丰富的体验。由于广泛部署到Web、手机和边缘设备&#xff0c;肖像分割在兼顾分割精度的…

TinyEMU源码分析之虚拟机初始化

TinyEMU源码分析之虚拟机初始化 1 初始化结构参数2 配置RAM地址空间3 初始化设备4 拷贝BIOS和Kernel5 手动写入5条指令6 体验第一条指令的执行 本文属于《 TinyEMU模拟器基础系列教程》之一&#xff0c;欢迎查看其它文章。 本文中使用的代码&#xff0c;均为伪代码&#xff0c…

【LeetCode】--- 动态规划 集训(一)

目录 一、1137. 第 N 个泰波那契数1.1 题目解析1.2 状态转移方程1.3 解题代码 二、面试题 08.01. 三步问题2.1 题目解析2.2 状态转移方程2.3 解题代码 三、746. 使用最小花费爬楼梯3.1 题目解析3.2 状态转移方程3.3 解题代码 一、1137. 第 N 个泰波那契数 题目地址&#xff1a…

Python中的线程池与进程池:并行编程的高效选择【第145篇—并行编程】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Python中的线程池与进程池&#xff1a;并行编程的高效选择 在Python编程中&#xff0c;实现…

[Linux]条件变量:实现线程同步(什么是条件变量、为什么需要条件变量,怎么使用条件变量(接口)、例子,代码演示(生产者消费者模式))

目录 一、条件变量 1.什么是条件变量 故事说明 2、为什么需要使用条件变量 竞态条件 3.什么是同步 饥饿问题 二、条件变量的接口 1.pthread_cond_t 2.初始化&#xff08;pthread_cond_init&#xff09; 3.销毁&#xff08;pthread_cond_destroy&#xff09; 4.等待&…

联发科MT8797迅鲲1300T规格参数_MTK5G安卓核心板方案定制

联发科MT8797&#xff08;迅鲲1300T&#xff09;平台采用Arm Cortex-A78和Cortex-A55组成的八核架构CPU&#xff0c;以及Arm Mali-G77MC9九核GPU&#xff0c;集成了AI处理器MediaTek APU&#xff0c;支持5G Sub-6GHz全频段和5G双载波聚合,支持1.08亿像素拍照和多镜头组合,以及1…

《逆水寒》“公费追星”被骂上热搜,玩家为何如此抗拒剧游联动?

游戏行业最近真是风波不断。 《逆水寒》手游因为和武侠剧《莲花楼》深入联动而遭到玩家抵制&#xff0c;网易游戏测评总监被质疑“公费追星”&#xff0c;还波及到了成毅、陈都灵等多位演员。 尤其是《莲花楼》的男主角成毅&#xff0c;遭到大量《逆水寒》手游玩家的吐槽调侃…

Java项目:70 ssm小学生课外知识学习网站+vue

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 管理员&#xff1b;首页、个人中心、医护人员管理、科室管理、病人管理、病房管理、病人信息管理、病历管理、医嘱管理、手术安排管理、药品信…

Shell脚本学习-if循环

最小化的if语句 无实际用途 if [ ] ;then echo fi 脚本解释 if 判断 [ ] 里面的条件是否成立 后面跟then&#xff0c;代表条件成立 如果在一行则使用分号隔离&#xff08;;&#xff09; 如果不在一行使用则直接在下一行驶入then即可。 如果条件成立则输出echo 后面…

GEC6818——QT开发之两个UI界面切换与表格显示DHT11数据

GEC6818——QT开发之两个UI界面切换与表格显示DHT11数据 使用环境: ubantu16 QT5.7 开发板GEC6818 实现要求&#xff1a; 利用A53按键1、按键2与温湿度传感器完成QT界面动态显示温湿度记录&#xff0c;并指定温湿度记录超过指定范围&#xff0c;进行报警&#xff08;LED&#…

企业网络基础设施物理安全面临全新挑战

企业网络基础设施的物理安全是确保业务连续性和数据完整性的关键组成部分。随着技术的发展和环境的变化&#xff0c;这些基础设施面临着新的挑战。以下是一些主要的挑战和的解决方案 一、机房、仓库、档案馆物理安全事件频发的挑战&#xff1a; 1.电力安全事件&#xff1a;市…

HTML5+CSS3+JS小实例:创意罗盘时钟

实例:创意罗盘时钟 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=…

优惠:阿里云4核16G服务器优惠价格26.52元1个月、149.00元半年

阿里云4核16G服务器优惠价格26.52元1个月、79.56元3个月、149.00元半年&#xff0c;配置为阿里云服务器ECS经济型e实例ecs.e-c1m4.xlarge&#xff0c;4核16G、按固定带宽 10Mbs、100GB ESSD Entry系统盘&#xff0c;活动链接 aliyunfuwuqi.com/go/aliyun 活动链接打开如下图&a…