【笔记】Go项目通过脚本自动重写String方法

前言

通过Python3编写脚本,实现自动重写Go项目所有结构体的String()方法
如果在Go语言的结构体中如果定义的属性都是指针类型,那么在输出打印在控制台是只会输出十六进制内存地址,不便于调试代码
重写结构体的String()方法,能控制fmt.Println()输出到控制台时的内容

源代码

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import os
import re

"""
自动重写所有结构体的String()方法,方便DEBUG调试的时候输出正确的数据而不是指针
当前版本只能重写`*int`、`*string`、`*bool`这几种类型的结构体属性的输出内容,其他类型和自定义类型都会跳过
"""

# 定义实体结构体的代码存放目录
workDir = "../model"

if __name__ == '__main__':
# 列出所有文件
fileNameList = os.listdir(workDir)
# 去除go.mod
fileNameList.remove("go.mod")
# print(fileNameList)
file_for_write = open(f"{workDir}/OverwriteStringmethod.go", "w")
file_for_write.write("package model\n\nimport \"fmt\"\n\n")
# 遍历所有文件名
for fileName in fileNameList:
# 只读文件
# print(f"{workDir}/{fileName}")
file_for_read = open(f"{workDir}/{fileName}", "r")
# 判定是否进入到了结构体内部,True进入到了,False跳出了
flag_in_struct = False
# 定义结构体名
structName = ""
# 定义格式化的字符串列表
format_str_list = []
# 定义属性名列表
field_name_list = []
while True:
# 按行读取文件内容
line = file_for_read.readline()
# 如果到文件末尾就退出读取
if not line:
break
# 输出当前行
# print(line, end="")

# 判定是否为结构体开始
if re.findall("type \\w+ struct {", line.strip()):
structName = line.strip()[5:-9]
flag_in_struct = True
continue

# 判断是否为结构体结束
if flag_in_struct and line.strip() == "}":
flag_in_struct = False
# 结构体变量名
structObjectName = structName[0].lower() + structName[1:]
# 定义输出的内容
s = ""
s += f"func ({structObjectName} {structName}) String() string {{\n"
s += f"\treturn fmt.Sprintf(\n"
s += f"\t\t\"{{"
for index in range(len(format_str_list)):
if index != 0:
s += " "
s += format_str_list[index]
s += f"}}\",\n"
for field_name in field_name_list:
s += f"\t\t*{structObjectName}.{field_name},\n"
s += f"\t)\n"
s += f"}}\n\n"
# 输出到文件
file_for_write.write(s)
# 清空结构体名
structName = ""
# 清空格式化的字符串列表
format_str_list = []
# 清空属性名列表
field_name_list = []
continue

# 判断是否为结构体主体部分
if flag_in_struct:
# 为`格式化的字符串列表`插入数据
if line.find("*int") != -1:
format_str_list.append("%d")
elif line.find("*string") != -1:
format_str_list.append("%s")
elif line.find("*bool") != -1:
format_str_list.append("%t")
else:
continue
# 为`属性名列表`插入数据
line.lstrip()
index = re.match("\t\\w+", line).span()
field_name_list.append(line[index[0]:index[1]].strip())
# print(field_name_list)

# 关闭文件
file_for_read.close()
file_for_write.close()

完成