不器小窝 不器小窝
首页
随笔
  • GoLang
  • 前端

    • Vue
    • VuePress
  • 开发工具
  • 系统工具
读吧
  • ToDb (opens new window)
  • goKit (opens new window)
  • 友情链接
  • 免费信息
  • 时间线
  • 关于
GitHub (opens new window)

不器

知行合一
首页
随笔
  • GoLang
  • 前端

    • Vue
    • VuePress
  • 开发工具
  • 系统工具
读吧
  • ToDb (opens new window)
  • goKit (opens new window)
  • 友情链接
  • 免费信息
  • 时间线
  • 关于
GitHub (opens new window)
  • GoLang

    • GoLang 安装
    • Go经验
      • 前言
      • 一行代码过多如何处理
        • 字符串
        • 链式表达式
      • 递归方法注意事项
      • 字符串拼接
        • +
        • sprintf
        • Join
        • buffer.WriteString
        • * buffer.Builder官方推荐使用
      • Slice转[]byte
        • 方法一
        • 方法二
      • 如何给golang项目打包
      • 切片增加数据
      • 获取struct中的别名
      • struct使用json.Marshal转换后值是空的
      • json数据格式化/缩进格式写入到json文件中
      • Go解析JSON时Key没有「引号」
        • 自行手动增加引号
        • 使用JSON5进行处理
      • 将字符串中Unicode字符转换为汉字
      • interface 转 string,int,float64
      • 防止在go开发中出现import cycle not allowed
      • 类型转换
        • interface{}转map
      • 如何定义类似Java的枚举
      • 递归函数的灵异事件
    • 错误集合
    • 基础库

    • 第三方库

    • Fyne

    • Wails

    • GoFrame

  • Dart

  • Markdown

  • 语言
  • GoLang
不器
2022-08-24
目录

Go经验

# 前言

本文是记录在Go开发中遇到的一些小经验,持续更新。

# 一行代码过多如何处理

# 字符串

//使用 `
str := `hello
world
v2.0`
//使用 +
//注意使用连接符的时候需要把连接符放在上一行占位,不然在编译的时候会自动加上当前代码结束的标示
str := "hello" +
"world" +
"v2.0"
1
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

# 递归方法注意事项

在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

# 字符串拼接

# +

s1 := "字符串"
s2 := "拼接"
s3 := s1 + s2
fmt.Print(s3)
//s3 = "打印字符串"
1
2
3
4
5

# sprintf

s1 := "字符串"
s2 := "拼接"
s3 := fmt.Sprintf("%s%s", s1, s2)
//s3 = "打印字符串"
1
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

# 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

# * 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

# 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

显示结果

[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

# 方法二

 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

显示结果

[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

# 如何给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

# 获取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

# 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

# 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

# 使用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

# 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

输出

string jack
int 1
float64 12.223
1
2
3

# 防止在go开发中出现import cycle not allowed

不同文件夹中代码中的交叉引用算是比较常见的,如果是映射出现这类问题我还能理解,但是go偏偏是直接语法上干掉了交叉引用的可能性,导致不可用的形态。想要处理这类问题,最好的方案莫过于在即将饮用的文件上添加一个文件夹,让其代码更深一层,从go的逻辑出发的话,这两个文件并不属于同一个包内

优点:解决了交叉引用的问题

缺点:文件结构变复杂了

# 类型转换

其它类型进行转换也类似interface{}转map

# interface{}转map

// 假定变量a目前表现的变量是interface{},底层实际变量是map[string]interface{}
a.(map[string]interface{})
1
2

# 如何定义类似Java的枚举

使用golang自定义类型

    type TimeUnit string
    
    const(
        TimeSecond TimeUnit = 'Seconds'
        TimeMinute TimeUnit = 'Minute'
        TimeHour TimeUnit = 'Hour'
    )
1
2
3
4
5
6
7

# 递归函数的灵异事件

在函数体中使用递归发现莫名的被中断,日志也未抛出,结果发现递归函数执行后直接向下执行了而不是进入递归函数中,此现象目前在递归函数后追加了一个return临时处理

#GoLang#小技巧#经验
更新时间: 2023/2/27 10:33:46
GoLang 安装
错误集合

← GoLang 安装 错误集合→

最近更新
01
Vue-pure-Admin基础
03-16
02
WebStorm工具使用手册
03-15
03
Windows
03-12
更多文章>
Theme by Vdoing | Copyright © 2022-2023 不器 | 小窝
sitemap icon by Icons8
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式