python class 定义迁移到 go struct
2025年8月11日大约 2 分钟
python class 定义迁移到 go struct
在 python 迁移到 go 的过程中,面对已经成型的对象类定义,迁移和修改类定义不同于逻辑代码,是很枯燥痛苦的过程。
通过以下脚本文件可以实现快速转换。
gen_struct.py
使用注意
- 如果字段名称中包含
dict
字符串,可能被替换修改,如果出现该问题,请根据实际业务情况修改map_go_type
方法。 msg
tag 为我个人业务需求,可以直接删除或修改为其他tag。
import io
import regex
class_name_reg = regex.compile(r"class\s(?P<name>[a-zA-Z0-9]+)(\(BaseModel\))?:")
single_line_doc_reg = regex.compile(r'""".*"""')
field_reg = regex.compile(r"(?P<name>[a-z-A-Z0-9]+):\s*(?P<type>\S+)\s*=?\s*(?P<default>\S+)?\s*#?(?P<descript>.*)?")
with io.open("struct", "rb") as f:
const_file = f.read().decode("utf-8")
lines = const_file.split("\n")
class_entry = ""
field_list = []
doc_entry = False
class FieldDeclaration:
name: str
type: str
default: str
descript: str
def __init__(self, reg_group):
self.name = reg_group['name']
self.type = reg_group['type']
self.default = reg_group['default']
self.descript = reg_group['descript']
class ClassDeclaration:
name: str
fields: list[FieldDeclaration]
def __init__(self, name, fields):
self.name = name
self.fields = fields
class_list = []
for line in lines:
line = line.strip()
if not class_entry and line.startswith("class"):
class_entry = class_name_reg.match(line).groups()[0]
continue
if class_entry:
if single_line_doc_reg.match(line):
continue
# multi lines doc
if line == '"""':
if doc_entry:
doc_entry = False
else:
doc_entry = True
continue
if doc_entry:
continue
# emtpy line, class scope escape
if not line:
if class_entry:
# class store
class_list.append(ClassDeclaration(class_entry, field_list))
class_entry = ""
field_list = []
continue
# field
field_list.append(FieldDeclaration(field_reg.match(line).groupdict()))
def upper_camel(s) -> str:
return s[0].upper() + s[1:]
def map_go_type(s) -> str:
s = s.replace("[str]", "[string]")
s = s.replace("dict", "map[string]any")
if s.startswith("Optional["):
s = s[9:-1]
if s.startswith("list["):
s = f"[]{s[5:-1]}"
if s == "str":
s = "string"
if s == "list":
s = "[]any"
return s
clz_sb = []
for clz in class_list:
sb = [
f"// {upper_camel(clz.name)} generated by gen_struct.py",
f"type {upper_camel(clz.name)} struct{{",
"\n".join([f' {upper_camel(f.name)}\t{map_go_type(f.type)}\t`json:"{f.name}" msg:"{f.name}"`' for f in clz.fields]), "}",
]
clz_sb.append("\n".join(sb))
with io.open("struct_out", "w") as f:
f.write("\n\n".join(clz_sb))
使用
读取文件:struct
class User(BaseModel):
"""profile.user"""
userId: int
name: str
rank: int
生成文件:struct_out
// User generated by gen_struct.py
type User struct{
UserId int `json:"userId" msg:"userId"`
Name string `json:"name" msg:"name"`
Rank int `json:"rank" msg:"rank"`
}