最近学到的一些Go知识

2021-07-30 10:44:36 浏览数 (1)

最近学到的一些Go知识

1.log.Fatal()和panic()

os.Exit(code),当code为0,表示成功;非0,表示失败。

此时会产生下面结果:

  • 应用程序立即退出
  • defer函数不会执行

回到log.Fatal函数,在该函数中会先调用Output,随后调用os.Exit(1),那么产生的结果就是:

  • 打印输出内容
  • 退出应用程序
  • defer函数不会执行

回到panic函数,会产生以下几个核心点:

  • 函数立即停止执行
  • defer函数被执行
  • 返回给调用者

2../...

在进行单元测试时,我们通常使用:

代码语言:javascript复制
go test -v

这个只会在当前文件夹下生效,对于子目录不生效,那如果想生效所有子目录呢?也就是当前整个项目单测,则需要使用./...

代码语言:javascript复制
go test ./... -v

这个在测试自己的单元测试是否通过是非常重要的!

3.[:0]和nil

我们在使用切片时,通常需要对当前切片进行清空操作,如何实现呢?

[a我们可以采用[:0]或者nil的方式。]

猜猜下面会输出什么:

代码语言:javascript复制
arr := []int{1, 2, 3}
a := arr[:]
a = nil
fmt.Println(a, len(a), cap(a))
b := arr[:]
b = b[:0]
fmt.Println(b, len(b), cap(b))

1) nil

当赋值为nil,垃圾回收器会自动回收原有数据。

所以,第一次的Println会输出,[] 0 0。

2)[:0]

如果我们还需要保存原有的切片内存,最佳方式是re-slice,第二次输出,[] 0 3。

4.template

template实现了数据驱动的用于生成文本输出的模版。

在工作中有个需求,就是写个sql去对库进行插入、更新等操作。

那通常的方式是去拼接一个sql语句,但是这样会拼接出错。诸如下面这样:

代码语言:javascript复制
sq := "select * from user where id = "   id

当字段太多就需要拼接很多了,此时容易出错,而模版变可以方便的生成sql字符串,再配上正则简直屌爆。

先来聊聊模版可以做什么,然后再回顾到本文的sql需求上。

1) 变量

通过创建一个变量,使用模版的New创建一个模版,并解析出传递进去的字符串。

代码语言:javascript复制
str := "world"
tmpl, err := template.New("hello world").Parse("hello, {{.}}n")
if err != nil {
  panic(err)
}
err = tmpl.Execute(os.Stdout, str)
if err != nil {
  panic(err)
}

当然,还可以传递结构体哦。像下面这样通过.直接访问结构体成员。

代码语言:javascript复制
type User struct {
 Name string
 Id   uint
}

func main() {
 sweaters := User{"wli", 1}
 tmpl, err := template.New("test").Parse("{{.Name}} of {{.Id}}n")
 if err != nil {
  panic(err)
 }
 err = tmpl.Execute(os.Stdout, sweaters)
 if err != nil {
  panic(err)
 }
}

自定义变量,通过$ 变量名方式创建新的变量,方法有参数,后面加参数即可。

注意传递方法时,该方法如果没有返回值直接报panic,模版对返回值有严格要求,第一种是只有一个返回值,第二个是第二个返回值必须是error。

代码语言:javascript复制
type User struct {
 Name string
 Id   uint
}

func (my *User) SayHello() string { //没参数
 return "hello"
}

func (my *User) SayYouName(name string) string { //有参数
 return "my name is : "   name
}

func main() {
 user := &User{Name: "wli", Id: 1}
 tmpl, err := template.New("test").Parse(`
 {{$str1 := .Name}}
 {{$str2 := .SayHello}}
 {{$str3 := .SayYouName .Name}}
 {{$str1}} {{$str2}} {{$str3}}`)
 if err != nil {
  panic(err)
 }
 err = tmpl.Execute(os.Stdout, user)
 if err != nil {
  panic(err)
 }
}

2) 函数

在变量那里提到了方法传递,当然函数传递也一样。

这里还有Funcs函数与FuncMao将函数添加到模版中,接口:

代码语言:javascript复制
func (t *Template) Funcs(funcMap FuncMap) *Template
type FuncMap map[string]interface{}

使用如:

代码语言:javascript复制
funcMap := template.FuncMap{
  "SayHello":   SayHello,
  "SayYouName": SayYouName,
}
name := "hello"
tmpl, err := template.New("test").Funcs(funcMap).Parse("{{SayHello}}n{{SayYouName .}}n")

在模版中,还预定义了一些全局函数,可以直接在{{}}中使用。

例如:print、index、len等。

代码语言:javascript复制
print、printf、println、index、len、call、js、html、or、and、not

使用如:

代码语言:javascript复制
s := []int{1, 2, 3}
tmpl, err := template.New("test").Parse(`{{printf "% vn" .}}{{ len .}}`)
if err != nil {
  panic(err)
}
err = tmpl.Execute(os.Stdout, s)
if err != nil {
  panic(err)
}

3) range

假设Friends是个数组,里面包含了很多Friend,每个Friend结构为:

代码语言:javascript复制
type Friend struct {
 Fname string
 Flag  bool
}

我们可以通过range遍历每个Friend。

代码语言:javascript复制
{{with .Friends}}
{{range .}}
{{$.UserName}} friend name is {{.Fname}}

{{end}}
{{end}}

4) if

只支持bool类型。

代码语言:javascript复制
{{if .Flag}}
 flag 
{{else}}
 not flag
{{end}}

前面综合例子:

代码语言:javascript复制
import (
 "os"
 "text/template"
)

type Friend struct {
 Fname string
 Flag  bool
}

type Person struct {
 UserName string
 Emails   []string
 Friends  []*Friend
}

func main() {
 f1 := Friend{Fname: "f1 name", Flag: false}
 f2 := Friend{Fname: "f2 name", Flag: true}
 t := template.New("template example")
 t, _ = t.Parse(`hello {{.UserName}}, 
 {{range .Emails}}
  email = {{.}} 
 {{end}} 
 {{with .Friends}}
 {{range .}}
  {{$.UserName}} friend name is {{.Fname}}
  {{if .Flag}}
   flag 
  {{else}}
   not flag
  {{end}}
 {{end}}
 {{end}}
 `)
 p := Person{UserName: "francis",
  Emails:  []string{"francis@beego.me", "francis@gmail.com"},
  Friends: []*Friend{&f1, &f2},
 }
 t.Execute(os.Stdout, p)
}

最后,回到我们的sql例子。

代码语言:javascript复制
type User struct {
 ID       string
 UserName string
 Age      int
 Date     string
}
t := template.New("userInsertTemplate")
sql := `
select * from user where ID='{{.ID}}' 
and date='{{.Date}}'
`
t, err := t.Parse(sql)
record := User{
  ID:   "123",
  Date: "2021-07-08",
}
out := strings.Builder{}
if err := t.Execute(&out, record); err != nil {
  return
}
fmt.Println(out.String())
// 去除空格、换行、空白符 匹配一个或多个空白符的正则表达式
spaceReg, _ := regexp.Compile(`s `)
sqlQuery := spaceReg.ReplaceAllString(out.String(), " ")
fmt.Println(sqlQuery

到这里便可以输出完整的sql了。

本节完~

0 人点赞