前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >最近学到的一些Go知识

最近学到的一些Go知识

作者头像
公众号guangcity
发布2021-07-30 10:44:36
3010
发布2021-07-30 10:44:36
举报
文章被收录于专栏:光城(guangcity)

最近学到的一些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 "%+v\n" .}}{{ 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了。

本节完~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 最近学到的一些Go知识
  • 1.log.Fatal()和panic()
  • 2../...
  • 3.[:0]和nil
  • 4.template
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档