我对golang泛型还不熟悉,目前有以下的设置。
- 我已经收集了许多不同类型的报告。
- 每个报告都有封闭字段
- 所以我将它包装在一个
ReportContainerImpl
中
我使用了一个类型参数[T Reportable]
,其中Reportable
的定义如下:
type Reportable interface {
ExportDataPointReport | ImportDataPointReport | MissingDataPointReport | SensorThresoldReport
}
类型约束中的每个类型都是要嵌入到容器中的结构体。
type ReportContainerImpl[T Reportable] struct {
LocationID string `json:"lid"`
Provider string `json:"pn"`
ReportType ReportType `json:"m"`
Body T `json:"body"`
}
我使用一个鉴别器ReportType
来确定在Unmarshal
时具体的类型。
type ReportType string
const (
ReportTypeExportDataPointReport ReportType = "ExportDataPointReport"
ReportTypeImportDataPointReport ReportType = "ImportDataPointReport"
ReportTypeMissingDataPointReport ReportType = "MissingDataPointReport"
ReportTypeSensorThresoldReport ReportType = "SensorThresoldReport"
)
由于 go 不支持对 struct 进行类型断言(仅限 interfaces),因此在 Unmarshal
时无法进行类型转换。此外,go 不支持指向 "raw" 泛型类型的指针。因此,我创建了一个 interface,由 ReportContainerImpl
实现。
type ReportContainer interface {
GetLocationID() string
GetProvider() string
GetReportType() ReportType
GetBody() interface{}
}
我遇到的问题是,无论如何都不能对返回类型进行类型约束,在
GetBody()
函数上回到"自由文本语义",以允许在完成Unmarshal
时进行类型断言。 container, err := UnmarshalReportContainer(data)
if rep, ok := container.GetBody().(ExportDataPointReport); ok {
// Use the ReportContainerImpl[ExportDataPointReport] here...
}
也许我理解有误?但是无论如何,我总是需要一个
interface{}
或在 Unmarshal
之前知道 确切的 类型才能完成某些操作。
- 你有更好的建议以更安全的方式解决这个问题吗?
谢谢, Mario :)
为了完整起见,我在这里添加了 UnmarshalReportContainer
。
func UnmarshalReportContainer(data []byte) (ReportContainer, error) {
type Temp struct {
LocationID string `json:"lid"`
Provider string `json:"pn"`
ReportType ReportType `json:"m"`
Body *json.RawMessage `json:"body"`
}
var temp Temp
err := json.Unmarshal(data, &temp)
if err != nil {
return nil, err
}
switch temp.ReportType {
case ReportTypeExportDataPointReport:
var report ExportDataPointReport
err := json.Unmarshal(*temp.Body, &report)
return &ReportContainerImpl[ExportDataPointReport]{
LocationID: temp.LocationID,
Provider: temp.Provider,
ReportType: temp.ReportType,
Body: report,
}, err
// ...
}
}