Go语言文本编码处理
[toc]
前言
有时候,我们需要用到Go语言处理一些很特殊的业务,就比如说我的仓库,如果不用程序的化,依次去编写文章是非常消耗时间和精力的,这个时候脚本或者程序代码可以帮助我们解决很多事情,比如说我现在的需求是:我需要用Go语言编写一个程序,满足下面的需求:
- 可以创建文件夹,和
README.md
文件 - 可以按照不同人或者不同的项目需要来编写程序代码
- 可以读取电脑上面的文件
- 在每一个文件里面,需要准备基本的模板
- 在
README.md
中也写入基本的模板 - 导入或者下载项目所需要的工具或者脚本
判断是否字符串是否包含字符串
介绍strings使用方法
package main
import (
"fmt"
"strings"
)
func main() {
s := "hello word!"
fmt.Println(strings.Contains(s, "hello"), strings.Contains(s, "?"))
}
编译:
PS C:\Users\smile\Desktop\区块链\code\gin> go run .\main.go
true false
包含hello返回true,不包含?返回false
看下contains源码
// Contains reports whether substr is within s.
func Contains(s, substr string) bool {
return Index(s, substr) >= 0
}
字符串拆分
package main
import (
"fmt"
"strings"
)
func main() {
s := "hello word!"
fmt.Println(strings.Contains(s, "hello"), strings.Contains(s, "?"))
ss := "a&s*a##av"
splitedStr := strings.Split(ss, "#")
fmt.Println(splitedStr)
}
编译:
PS C:\Users\smile\Desktop\区块链\code\gin> go run .\main.go
true false
[a&s*a av]
看下源码
func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
// SplitAfter slices s into all substrings after each instance of sep and
// returns a slice of those substrings.
//
// If s does not contain sep and sep is not empty, SplitAfter returns
// a slice of length 1 whose only element is s.
//
// If sep is empty, SplitAfter splits after each UTF-8 sequence. If
// both s and sep are empty, SplitAfter returns an empty slice.
//
// It is equivalent to SplitAfterN with a count of -1.
func SplitAfter(s, sep string) []string {
return genSplit(s, sep, len(sep), -1)
}
可以使用join将其合并起来
fmt.Println("string.Join(splitedStr,"#"))
看下join源码
func Join(elems []string, sep string) string {
switch len(elems) {
case 0:
return ""
case 1:
return elems[0]
}
n := len(sep) * (len(elems) - 1)
for i := 0; i < len(elems); i++ {
n += len(elems[i])
}
var b Builder
b.Grow(n)
b.WriteString(elems[0])
for _, s := range elems[1:] {
b.WriteString(sep)
b.WriteString(s)
}
return b.String()
}
字符串转化
package main
import (
"fmt"
"strconv"
)
func main() {
s := "zxcvzbnznz"
fmt.Println("s=", s)
fmt.Println(strconv.Itoa(100))
// func Itoa(i int) string {
// return FormatInt(int64(i), 10)
// }
a, err := strconv.Atoi("12")
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println(a)
}
编译:
PS C:\Users\smile\Desktop\区块链\code\gin> go run .\main.go
s= zxcvzbnznz
100
12
继续
package main
import (
"fmt"
"strconv"
)
func main() {
s := "zxcvzbnznz"
fmt.Println("s=", s)
fmt.Println(strconv.Itoa(100))
// func Itoa(i int) string {
// return FormatInt(int64(i), 10)
// }
a, err := strconv.ParseBool("t")
if err != nil {
fmt.Println("err = ", err)
return
}
/*func ParseBool(str string) (bool, error) {
switch str {
case "1", "t", "T", "true", "TRUE", "True":
return true, nil
case "0", "f", "F", "false", "FALSE", "False":
return false, nil
}
return false, syntaxError("ParseBool", str)
}*/
fmt.Println("a=", a)
a1, err1 := strconv.ParseFloat("123.2134", 64)
if err1 != nil {
fmt.Println("err = ", err)
return
}
/*func ParseFloat(s string, bitSize int) (float64, error) {
f, n, err := parseFloatPrefix(s, bitSize)
if n != len(s) && (err == nil || err.(*NumError).Err != ErrSyntax) {
return 0, syntaxError(fnParseFloat, s)
}
return f, err
}*/
fmt.Println("a1=", a1)
}
编译:
PS C:\Users\smile\Desktop\区块链\code\gin> go run .\main.go
s= zxcvzbnznz
100
a= true
a1= 123.2134
序列化和反序列化
package main
import (
"encoding/xml"
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
p := Person{"smiel", 19}
fmt.Println("person = ", p)
if data, err := xml.Marshal(p); err != nil {
fmt.Println("err = ", err)
return
} else {
fmt.Println(string(data))
}
/*func Marshal(v any) ([]byte, error) {
var b bytes.Buffer
if err := NewEncoder(&b).Encode(v); err != nil {
return nil, err
}
return b.Bytes(), nil
}*/
}
编译:
PS C:\Users\smile\Desktop\区块链\code\gin> go run .\main.go
person = {smiel 19}
<Person><Name>smiel</Name><Age>19</Age></Person>
这个默认不是可读性的xml需要格式化
xml.MarshalIndent(p,""," ")
- 第二个:前缀
- 第三个:缩进
底层源码
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
var b bytes.Buffer
enc := NewEncoder(&b)
enc.Indent(prefix, indent)
if err := enc.Encode(v); err != nil {
return nil, err
}
return b.Bytes(), nil
}
此时还有一个小技巧,我的err放在if语句中,此时可以确定作用域仅仅在if语句中
使用flag获取复杂参数
package main
import (
"flag"
"fmt"
)
func main() {
methodPtr := flag.String("method", "default", "method of sample")
//func String(name string, value string, usage string) *string {
//return CommandLine.String(name, value, usage)}
valuePtr := flag.Int64("value", -1, "value of sample")
flag.Parse()
fmt.Println(*methodPtr, *valuePtr)
}
编译:
C:\Users\smile\Desktop\区块链\code\gin>go build main.go
C:\Users\smile\Desktop\区块链\code\gin>a.exe
'a.exe' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
C:\Users\smile\Desktop\区块链\code\gin>go build main.go
C:\Users\smile\Desktop\区块链\code\gin>main.exe
default -1
C:\Users\smile\Desktop\区块链\code\gin>main.exe -method helloxiongxinwei@mail.com
helloxiongxinwei@mail.com -1
控制命令行操作
package main
import (
"bufio"
"bytes"
"fmt"
"os/exec"
)
func cmd1() {
//首先生成cmd结构体,该结构体包含了很多信息,如执行命令的参数,命令的标准输入输出等
command := exec.Command("ls", "-l")
//给标准输入以及标准错误初始化一个buffer,每条命令的输出位置可能是不一样的,
//比如有的命令会将输出放到stdout,有的放到stderr
command.Stdout = &bytes.Buffer{}
command.Stderr = &bytes.Buffer{}
//执行命令,直到命令结束
err := command.Run()
if err != nil {
//打印程序中的错误以及命令行标准错误中的输出
fmt.Println(err)
fmt.Println(command.Stderr.(*bytes.Buffer).String())
return
}
//打印命令行的标准输出
fmt.Println(command.Stdout.(*bytes.Buffer).String())
}
func cmd2() {
//首先生成cmd结构体
cmd := exec.Command("strace", "-p", "15284")
//调用stderrPipe生成一个管道,该管道连接到命令行进程的标准错误, 该方法返回一个
//ReadCloser, 我们可以通过读取返回的ReadCloser来实时读取命令行进程的标准错误
piper, _ := cmd.StderrPipe()
//开始执行命令
cmd.Start()
//使用bufio包封装的方法实现对reader的读取
reader := bufio.NewReader(piper)
for {
//换行分隔
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println(err)
break
}
//打印内容
fmt.Println(line)
}
//等待命令结束并回收子进程资源等
cmd.Wait()
}
func main() {
fmt.Println("调用cmd1函数:")
cmd1()
fmt.Println("调用cmd2函数:")
cmd2()
command := exec.Command("ifconfig")
command.Stdout = &bytes.Buffer{}
command.Stderr = &bytes.Buffer{}
//执行命令,直到命令结束
err := command.Run()
if err != nil {
//打印程序中的错误以及命令行标准错误中的输出
fmt.Println(err)
fmt.Println(command.Stderr.(*bytes.Buffer).String())
return
}
fmt.Println(command.Stdout.(*bytes.Buffer).String())
}
查看底层源码:
func Command(name string, arg ...string) *Cmd {
cmd := &Cmd{
Path: name,
Args: append([]string{name}, arg...),
}
if filepath.Base(name) == name {
if lp, err := LookPath(name); err != nil {
cmd.lookPathErr = err
} else {
cmd.Path = lp
}
}
return cmd
}
补充:变量的作用域
package main
import (
"fmt"
)
func style(method string, value int) {
//this.method = method
method = "smile3"
value = 1003
fmt.Println(method)
fmt.Println(value)
}
func style2() {
var method string
var value int
method = "smile"
value = 100
fmt.Println(method)
fmt.Println(value)
}
func main() {
var method string
var value int
method = "hello main"
value = 10
fmt.Println(method)
fmt.Println(value)
fmt.Println(" === ")
style2()
fmt.Println(" === ")
fmt.Println(method)
fmt.Println(value)
fmt.Println(" === ")
style(method, value)
fmt.Println(" == 3")
fmt.Println(method)
fmt.Println(value)
}
编译:
C:\Users\smile\Desktop\区块链\code\gin>go run main.go
hello main
10
===
smile
100
===
hello main
10
===
smile3
1003
== 3
hello main
10