如何将数据从一种类型复制到具有相同结构的另一种类型?
How to copy data from one type to another that has identical structures?
在下面的代码中:
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
}
如何将数据从一种类型复制到具有相同结构的另一种类型?因为 RequestBody
和 ProductEntityList
是两个不同的类型定义
如果这些类型真的相等,使用type alias:
type PostRequestModel = ProductEntity
如果这样做,您可以简单地将 ProductEntityList
转换为 RequestBody
(在 Go Playground 上尝试):
func convertModelToEntity(modelList RequestBody) ProductEntityList {
return ProductEntityList(modelList) // Works!!
}
如果不能使用类型别名,则无法从一个切片转换为另一个切片。您必须创建一个新切片。请注意,您可以转换单个切片元素,因为指向的结构类型具有相同的字段。这是可能的,因为 Spec: Conversions:
A non-constant value x
can be converted to type T
in any of these cases:
- [...]
- ignoring struct tags (see below),
x
's type and T
are pointer types that are not defined types, and their pointer base types have identical underlying types.
因此 *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
}
另请注意,如果 RequestBody
和 ProductEntityList
具有相同的内存布局(在您的示例中是相同的),您可以使用包 unsafe
to simply convert them, but I'd rather avoid it (try it on the Go Playground):
func convertModelToEntity(modelList RequestBody) ProductEntityList {
return *(*ProductEntityList)(unsafe.Pointer(&modelList))
}
为什么要避免这种情况?使用包 unsafe
你的应用程序可能变得不可移植并且 Go 1 兼容性保证可能不适用于它。例如。您只能将字段添加到 ProductEntity
而不能添加到 PostRequestModel
。因此,您的应用程序将继续编译而不会出现错误,但随时可能会崩溃。始终将软件包 unsafe
视为最后的手段。
在下面的代码中:
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
}
如何将数据从一种类型复制到具有相同结构的另一种类型?因为 RequestBody
和 ProductEntityList
是两个不同的类型定义
如果这些类型真的相等,使用type alias:
type PostRequestModel = ProductEntity
如果这样做,您可以简单地将 ProductEntityList
转换为 RequestBody
(在 Go Playground 上尝试):
func convertModelToEntity(modelList RequestBody) ProductEntityList {
return ProductEntityList(modelList) // Works!!
}
如果不能使用类型别名,则无法从一个切片转换为另一个切片。您必须创建一个新切片。请注意,您可以转换单个切片元素,因为指向的结构类型具有相同的字段。这是可能的,因为 Spec: Conversions:
A non-constant value
x
can be converted to typeT
in any of these cases:
- [...]
- ignoring struct tags (see below),
x
's type andT
are pointer types that are not defined types, and their pointer base types have identical underlying types.
因此 *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
}
另请注意,如果 RequestBody
和 ProductEntityList
具有相同的内存布局(在您的示例中是相同的),您可以使用包 unsafe
to simply convert them, but I'd rather avoid it (try it on the Go Playground):
func convertModelToEntity(modelList RequestBody) ProductEntityList {
return *(*ProductEntityList)(unsafe.Pointer(&modelList))
}
为什么要避免这种情况?使用包 unsafe
你的应用程序可能变得不可移植并且 Go 1 兼容性保证可能不适用于它。例如。您只能将字段添加到 ProductEntity
而不能添加到 PostRequestModel
。因此,您的应用程序将继续编译而不会出现错误,但随时可能会崩溃。始终将软件包 unsafe
视为最后的手段。