gpt4 book ai didi

go - 在运行时以编程方式创建结构 - 可能吗?

转载 作者:IT王子 更新时间:2023-10-29 01:49:28 25 4
gpt4 key购买 nike

是否可以在 Go 中以编程方式创建结构类型(即不在编译的源代码中)?

我们有一个特定的用例,其中将通过用户定义的元数据创建类型(因此模式/类型事先不知道)并且会因每个客户而异。然后,我们需要为这些服务自动生成 REST 服务,并将它们保存在 NoSQL 后端中。我们还需要为每个字段定义不同的动态验证器(例如强制、正则表达式、最大/最小大小、最大/最小值、对另一个类型实例的引用等)

我想知道在 Go 中是否可以做类似的事情?

编辑 1:

例如

From frontend in JSON

For customer 1:
{
"id":1,
"patientid":1,
"name":"test1",
"height":"160",
"weight":"70",
"temp":"98"
}

For customer 2:
{
"id":2,
"patientid":1,
"name":"test1",
"height":"160",
"weight":"70"
}

For customer 3

may be different new fields will add

Backend

// For One customer need to have these fields 

type Vitalsigns struct {
ID int64 `datastore:"-"`
PatientID int64 `json:"patientid,omitempty"`
Name string `json:"name,omitempty"`
Height string `json:"height,omitempty"`
Weight string `json:"weight,omitempty"`
Temp string `json:"temp,omitempty"`
}



// Another need to have these fields

type Vitalsigns struct {
ID int64 `datastore:"-"`
PatientID int64 `json:"patientid,omitempty"`
Name string `json:"name,omitempty"`
Height string `json:"height,omitempty"`
Weight string `json:"weight,omitempty"`
}


//CreateVitalsignsHandler is to create vitals for a patient
func CreateVitalsignsHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {

//Creating the Vitalsigns
kinVitalsigns := &Vitalsigns{}
ctx := appengine.NewContext(r)
if err := json.NewDecoder(r.Body).Decode(kinVitalsigns); err != nil {
RespondErr(w, r, http.StatusInternalServerError, err.Error())
return
}
//Getting namespace
namespace := ps.ByName("namespace")
ctx, err := appengine.Namespace(ctx, namespace)
if err != nil {
log.Infof(ctx, "Namespace error from CreateVitalsignsHandler")
RespondErr(w, r, http.StatusInternalServerError, err.Error())
return
}
//Geting the patientID
pID, err := strconv.Atoi(ps.ByName("id"))
if err != nil {
log.Infof(ctx, "Srting to Int64 conversion error from CreateVitalsignsHandler")
RespondErr(w, r, http.StatusInternalServerError, err.Error())
return
}
patientID := int64(pID)
kinVitalsigns.PatientID = patientID

//Generating the key
vitalsignsKey := datastore.NewIncompleteKey(ctx, "Vitalsigns", nil)

//Inserting the data to the datastore
vk, err := datastore.Put(ctx, vitalsignsKey, kinVitalsigns)
if err != nil {
log.Infof(ctx, "Entity creation was failed from CreateVitalsignsHandler")
RespondErr(w, r, http.StatusInternalServerError, err.Error())
return
}
kinVitalsigns.ID = vk.IntID()
message := "Vitalsigns created successfully!! "
Respond(w, r, http.StatusOK, SuccessResponse{kinVitalsigns.ID, 0, "", message})
return
}

最佳答案

编辑:您的编辑显示您想要处理动态对象以从 Google 数据存储中放入/检索。为此,完全没有必要在运行时创建结构类型,您可以只使用此答案中提供的动态映射:How can I have dynamic properties in go on the google app engine datastore .

原始答案如下。


请注意,如果类型在编译时已知,最好/最有效的方法是创建类型并编译它们,因此一切都将是“静态的”。您可以手动创建类型,也可以使用 go generate 来自动执行该过程。

另请注意,您可能不一定需要结构类型来为动态对象建模,很多时候映射可能就足够了。

如果类型在编译时未知,而结构类型是必须的,请继续阅读。

是的,可以使用 Go 的反射在运行时创建“动态”结构类型,特别是使用 reflect.StructOf()功能。

让我们看一个简单的例子,在运行时创建一个结构类型,它有一个 Name string 和一个 Age int 字段:

t := reflect.StructOf([]reflect.StructField{
{
Name: "Name",
Type: reflect.TypeOf(""), // string
},
{
Name: "Age",
Type: reflect.TypeOf(0), // int
},
})

fmt.Println(t)

v := reflect.New(t)
fmt.Printf("%+v\n", v)
v.Elem().FieldByName("Name").Set(reflect.ValueOf("Bob"))
v.Elem().FieldByName("Age").Set(reflect.ValueOf(12))

fmt.Printf("%+v\n", v)

此输出(在 Go Playground 上尝试):

struct { Name string; Age int }
&{Name: Age:0}
&{Name:Bob Age:12}

如果您想定义验证规则,您可以为此使用第三方库,例如 github.com/go-validator/validator .这个包使用 struct tags指定验证规则,您也可以使用反射指定结构标签。

例如,如果要指定Name必须最少3个字符,最多40个字符,并且只能包含英文字母,的有效范围年龄6..100(包括两者),这是它的样子:

t := reflect.StructOf([]reflect.StructField{
{
Name: "Name",
Type: reflect.TypeOf(""), // string
Tag: reflect.StructTag(`validate:"min=3,max=40,regexp=^[a-zA-Z]*$"`),
},
{
Name: "Age",
Type: reflect.TypeOf(0), // int
Tag: reflect.StructTag(`validate:"min=6,max=100"`),
},
})

打印此类型将输出(由我包装)(在 Go Playground 上尝试):

struct { Name string "validate:\"min=3,max=40,regexp=^[a-zA-Z]*$\"";
Age int "validate:\"min=6,max=100\"" }

创建此结构的实例后,您可以使用 validator.Validate() 对其进行验证功能,例如:

v := reflect.New(t)
v.Elem().FieldByName("Name").Set(reflect.ValueOf("Bob"))
v.Elem().FieldByName("Age").Set(reflect.ValueOf(12))

if errs := validator.Validate(v.Elem().Interface()); errs != nil {
// values not valid, deal with errors here
}

关于go - 在运行时以编程方式创建结构 - 可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55934210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com