我是 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的型別斷言(僅介面),因此無法在Unmarshal. 也不支持指向“原始”泛型型別的指標。因此,我創建了一個實作的介面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
- 你有更好的建議如何以一種型別(更安全)的方式解決這個問題嗎?
干杯,馬里奧 :)
為了完整起見,我在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
// ...
}
}
uj5u.com熱心網友回復:
但是無論我這樣做,我總是在某個地方需要一個介面{},或者在 Unmarshal 之前知道確切的型別
恰恰。
在撰寫代碼時,實體化某些泛型型別或函式所需的具體型別ReportContainerImpl或UnmarshalReportContainer必須在編譯時知道。JSON 解編組是在運行時發生的,當您使用實際資料填充位元組片時。
要根據一些歧視性值解組動態 JSON,您仍然需要一個switch.
你有更好的建議如何以一種型別(更安全)的方式解決這個問題嗎?
只需放棄引數多型性。這里不太適合。保留您現在擁有的代碼json.RawMessage,有條件地解組動態資料switch并回傳實作ReportContainer介面的具體結構。
附帶說明一下,如果您發現自己在撰寫具有多種結構型別的聯合,這也表明您可能需要使用普通的舊介面而不是型別引數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/464409.html
上一篇:通用函式中兩個容器的總和
