ove*_*nge -3 struct pointers go slice
在下面的代码中:
type ProductEntity struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Price float32 `json:"price"`
SKU string `json:"sku"`
CreatedOn string `json:"-"`
UpdatedOn string `json:"-"`
DeletedOn string `json:"-"`
}
type ProductEntityList []*ProductEntity
type PostRequestModel struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Price float32 `json:"price"`
SKU string `json:"sku"`
CreatedOn string `json:"-"`
UpdatedOn string `json:"-"`
DeletedOn string `json:"-"`
}
type RequestBody []*PostRequestModel
func convertModelToEntity(modelList RequestBody) ProductEntityList {
// return entity.ProductEntityList(modelList) // type conversion error
}
Run Code Online (Sandbox Code Playgroud)
如何将数据从一种类型复制到另一种具有相同结构的类型?因为RequestBody和ProductEntityList是两个不同的类型定义
如果这些类型确实相等,请使用类型别名:
type PostRequestModel = ProductEntity
Run Code Online (Sandbox Code Playgroud)
如果你这样做,你可以简单地转换ProductEntityList为RequestBody(在Go Playground上尝试):
func convertModelToEntity(modelList RequestBody) ProductEntityList {
return ProductEntityList(modelList) // Works!!
}
Run Code Online (Sandbox Code Playgroud)
如果不能使用类型别名,则不能从一个切片转换为另一个切片。您必须创建一个新切片。请注意,您可以转换单个切片元素,因为指向的结构类型具有相同的字段。这是可能的,因为规范:转换:
在以下任何一种情况下,非常量值
x都可以转换为类型T:
所以*ProductEntity可转化为*PostRequestModel(反之亦然),因为基础类型的ProductEntity和PostRequestModel是“相同”的结构类型。
在Go Playground上试试:
func convertModelToEntity(modelList RequestBody) ProductEntityList {
r := make(ProductEntityList, len(modelList))
for i, m := range modelList {
r[i] = (*ProductEntity)(m)
}
return r
}
Run Code Online (Sandbox Code Playgroud)
另请注意,如果RequestBody和ProductEntityList具有相同的内存布局(它们在您的示例中),您可以使用 packageunsafe来简单地转换它们,但我宁愿避免它(在Go Playground上尝试):
func convertModelToEntity(modelList RequestBody) ProductEntityList {
return *(*ProductEntityList)(unsafe.Pointer(&modelList))
}
Run Code Online (Sandbox Code Playgroud)
为什么要避免这种情况?使用包unsafe您的应用程序可能变得不可移植,并且 Go 1 兼容性保证可能不适用于它。例如,您可以将字段添加到ProductEntityonly 而不是 to PostRequestModel。因此,您的应用程序将继续编译而不会出错,但随时可能崩溃。始终将包裹unsafe视为最后的手段。