Go经验
# 前言
本文是记录在Go
开发中遇到的一些小经验,持续更新。
# 一行代码过多如何处理
# 字符串
//使用 `
str := `hello
world
v2.0`
//使用 +
//注意使用连接符的时候需要把连接符放在上一行占位,不然在编译的时候会自动加上当前代码结束的标示
str := "hello" +
"world" +
"v2.0"
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 链式表达式
把链式的连接符放在上一行的末尾即可
model := g.DB().Model(table).
Where("mobile", req.Mobile).
Where("id_no", req.IdNo)
1
2
3
2
3
# 递归方法注意事项
在go
中使用递归的时候会一层层的返回,而不是在递归内部返回时直接返回到顶部的形态
//输出
//3
//3
//1
//0
func main() {
fmt.Println(RandomPort(1))
}
// RandomPort 随机产生端口号,10000<=port<=65535
func RandomPort(m int) int {
randomStr := ""
for i := 0; i < 5; i++ {
value := time.Now().UnixMicro()
lastNum := value % 10
var build strings.Builder
if randomStr == "" {
build.WriteString(strconv.FormatInt(lastNum, 10))
randomStr = build.String()
} else {
build.WriteString(randomStr)
build.WriteString(strconv.FormatInt(lastNum, 10))
randomStr = build.String()
}
}
port, err := strconv.Atoi(randomStr)
if err != nil {
//如果获取失败则重新再来
port = RandomPort(2)
}
if 10e3 <= port && port <= 65535 {
return port
}
port = RandomPort(3)
fmt.Println(m)
return 0
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 字符串拼接
# +
s1 := "字符串"
s2 := "拼接"
s3 := s1 + s2
fmt.Print(s3)
//s3 = "打印字符串"
1
2
3
4
5
2
3
4
5
# sprintf
s1 := "字符串"
s2 := "拼接"
s3 := fmt.Sprintf("%s%s", s1, s2)
//s3 = "打印字符串"
1
2
3
4
2
3
4
# Join
//需要先导入strings包
s1 := "字符串"
s2 := "拼接"
//定义一个字符串数组包含上述的字符串
var str []string = []string{s1, s2}
//调用Join函数
s3 := strings.Join(str, "")
fmt.Print(s3)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# buffer.WriteString
//需要先导入bytes包
s1 := "字符串"
s2 := "拼接"
//定义Buffer类型
var bt bytes.Buffer
向bt中写入字符串
bt.WriteString(s1)
bt.WriteString(s2)
//获得拼接后的字符串
s3 := bt.String()
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# * buffer.Builder
官方推荐使用
//需要先导入Strings包
s1 := "字符串"
s2 := "拼接"
var build strings.Builder
build.WriteString(s1)
build.WriteString(s2)
s3 := build.String()
1
2
3
4
5
6
7
2
3
4
5
6
7
# Slice
转[]byte
# 方法一
package main
import (
"fmt"
"strings"
)
func convert(){
stringSlice := []string{"通知中心","perfect!"}
stringByte := "\x00" + strings.Join(stringSlice, "\x20\x00") // x20 = space and x00 = null
fmt.Println([]byte(stringByte))
fmt.Println(string([]byte(stringByte)))
}
func main() {
convert()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
显示结果
[0 233 128 154 231 159 165 228 184 173 229 191 131 2 0 112 101 114 102 101 99 116 33]
通知中心 perfect!
1
2
2
# 方法二
package main
import (
"bytes"
"encoding/gob"
"fmt"
)
func convert(){
stringSlice := []string{"通知中心","perfect!"}
buffer := &bytes.Buffer{}
gob.NewEncoder(buffer).Encode(stringSlice)
byteSlice := buffer.Bytes()
fmt.Printf("%q\n", byteSlice)
fmt.Println("---------------------------")
backToStringSlice := []string{}
gob.NewDecoder(buffer).Decode(&backToStringSlice)
fmt.Printf("%v\n", backToStringSlice)
}
func main() {
convert()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
显示结果
[0 233 128 154 231 159 165 228 184 173 229 191 131 2 0 112 101 114 102 101 99 116 33]
通知中心 perfect!
1
2
2
# 如何给golang
项目打包
将${name}
替换为要生成的名字
Windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ${name}.exe
1
Linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${name}
1
macOS
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ${name}
1
# 切片增加数据
arryV := make([]string, 1, 1)
for _, site := range list {
arryV = append(arryV, site.String())
}
1
2
3
4
2
3
4
# 获取struct
中的别名
type connectionType struct {
alias string `tag:"连接名"` //别名
hostURL string `tag:"连接地址"` //连接地址
port string `tag:"端口号"` //端口号
username string `tag:"用户名"` //用户名
password string `tag:"密码"` //密码
}
fieldV, _ := reflect.TypeOf(connectionType{}).FieldByName("alias")
tag := fieldV.Tag.Get("tag")
// 输出: 连接名
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# struct
使用json.Marshal
转换后值是空的
需要转换的struct
必须是可以被引用的,即struct
的首字母大写
# json
数据格式化/缩进格式写入到json
文件中
把数据进行序列话的时候使用MarshalIndent
方法,该方法按照json
格式 缩进
info := `{"alias":"11","hostURL":"11","port":"11","username":"11","password":"11","savePassword":true}`
_v, _ := json.MarshalIndent(info, "", " ")
fmt.Println(string(_v))
//显示效果
/**
{
"alias": "11",
"hostURL": "11",
"port": "11",
"username": "11",
"password": "11"
}
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# Go
解析JSON
时Key
没有「引号」
解决方案:
# 自行手动增加引号
reg:=regexp.MustCompile(`[\w]+[:]`)
reg.ReplaceAllStringFunc(resStr,func(s string) string{
reg2:=regexp.MustCompile(`[\w]+`)
s=reg2.FindAllString(s,-1)[0]
return `"`+s+`":`
})
1
2
3
4
5
6
2
3
4
5
6
# 使用JSON5
进行处理
具体包请搜索Github
# 将字符串中Unicode
字符转换为汉字
func UnicodeToZH(raw []byte) ([]byte, error) {
str, err := strconv.Unquote(strings.Replace(strconv.Quote(string(raw)), `\\u`, `\u`, -1))
if err != nil {
return nil, err
}
return []byte(str), nil
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# interface
转 string
,int
,float64
func interface2String(inter interface{}) {
switch inter.(type) {
case string:
fmt.Println("string", inter.(string))
break
case int:
fmt.Println("int", inter.(int))
break
case float64:
fmt.Println("float64", inter.(float64))
break
}
}
func main() {
interface2String("jack")
interface2String(1)
interface2String(12.223)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
输出
string jack
int 1
float64 12.223
1
2
3
2
3
# 防止在go
开发中出现import cycle not allowed
不同文件夹中代码中的交叉引用算是比较常见的,如果是映射出现这类问题我还能理解,但是go
偏偏是直接语法上干掉了交叉引用的可能性,导致不可用的形态。想要处理这类问题,最好的方案莫过于在即将饮用的文件上添加一个文件夹,让其代码更深一层,从go
的逻辑出发的话,这两个文件并不属于同一个包内
优点:解决了交叉引用的问题
缺点:文件结构变复杂了
# 类型转换
其它类型进行转换也类似
interface{}
转map
# interface{}
转map
// 假定变量a目前表现的变量是interface{},底层实际变量是map[string]interface{}
a.(map[string]interface{})
1
2
2
# 如何定义类似Java
的枚举
使用golang
自定义类型
type TimeUnit string
const(
TimeSecond TimeUnit = 'Seconds'
TimeMinute TimeUnit = 'Minute'
TimeHour TimeUnit = 'Hour'
)
1
2
3
4
5
6
7
2
3
4
5
6
7
# 递归函数的灵异事件
在函数体中使用递归发现莫名的被中断,日志也未抛出,结果发现递归函数执行后直接向下执行了而不是进入递归函数中,此现象目前在递归函数后追加了一个return
临时处理
更新时间: 2023/2/27 10:33:46