Golang如何优雅的转换两个相似的结构体?

36 min read

在Golang中,如果要将两个相似的结构体进行转换,可以使用反射进行操作。以下是一个示例代码:

package main

import (
	"fmt"
	"reflect"
)

type SourceStruct struct {
	ID   int
	Name string
}

type DestinationStruct struct {
	ID   int
	Name string
}

func main() {
	source := SourceStruct{ID: 1, Name: "John"}

	destination := convertStruct(source)

	fmt.Println(destination)
}

func convertStruct(source interface{}) DestinationStruct {
	sourceValue := reflect.ValueOf(source)

	if sourceValue.Kind() == reflect.Ptr {
		sourceValue = sourceValue.Elem()
	}

	destinationValue := reflect.New(reflect.TypeOf(DestinationStruct{})).Elem()

	for i := 0; i < sourceValue.NumField(); i++ {
		sourceFieldValue := sourceValue.Field(i)
		destinationFieldType := destinationValue.Field(i).Type()

		if sourceFieldValue.Type().ConvertibleTo(destinationFieldType) {
			destinationValue.Field(i).Set(sourceFieldValue.Convert(destinationFieldType))
		}
	}

	return destinationValue.Interface().(DestinationStruct)
}

在上面的代码中,首先定义了SourceStruct和DestinationStruct两个结构体。然后在main函数中,创建一个SourceStruct的实例source。

调用convertStruct函数将source转换为DestinationStruct类型。convertStruct函数使用反射对结构体进行转换。首先通过reflect.ValueOf获取source的Value对象,然后判断其类型是否为指针,如果是指针类型,则通过Elem方法获取到指针指向的结构体的Value对象。

接着创建一个空的DestinationStruct实例destination,并使用reflect.New创建其Value对象。

然后通过循环遍历source结构体的字段,获取到每个字段的值和对应的类型。判断字段的类型是否可转换为目标结构体的对应字段的类型,如果可以,则使用Convert方法进行转换并将值设置到destination结构体的字段中。

最后通过Interface方法将Value对象转换为DestinationStruct类型并返回。