不同結構轉換

不同結構轉轉後換

因為斷言只能用在相同結構的轉換,而相似結構的轉換則要用不同方式去進行.


type UserDetail struct {
	Name     string `json:"name"`
	Email    string `json:"email"`
	BirthDay string
	Addr     string
	Phone    string
	Age      int `json:"age"`
	Order    []order
}

type UserDetail2 struct {
	Name     string
	Email    string
	BirthDay string
	Addr     string
	Phone    string
	Age      int
	Order    []order
}
type UserBrief struct {
	Name  string `json:"name"`
	Email string `json:"email"`
	Age   int    
	Order []order
}

type order struct {
	ID   string
	Name string
}

func main() {
	user1 := UserDetail{Name: "anna", Age: 20, Addr: "star", Phone: "123456789", Email: "test@test.com",
		Order: []order{{ID: "01", Name: "name1"}, {ID: "02", Name: "name2"}},
	}
	fmt.Printf("Type:%T V(%v) Name:%s \n", user1, user1, user1.Name)
	user2 := UserDetail2(user1) //使用斷言 T(v) 相同結構struct(忽略struct tag)
	fmt.Printf("Type:%T V(%v) Name:%s \n", user2, user2, user2.Name)

	//user3 := UserBrief(user1) // 不能使用斷言 因為結構不同 會報錯 cannot convert user1 (variable of type UserDetail) to UserBriefcompiler

}

方法一

//方式一:自己寫轉換 一個欄位一個欄位對應
//缺點:如果欄位太多會寫到懷疑自己,而且容易漏
//優點 : 性能較好,可以自己處理錯誤訊息
func toUserBrief(payload UserDetail, u *UserBrief) error {
	if payload.Name == "" {
		return errors.Errorf("payload name empty")
	}
	u.Age = payload.Age
	u.Name = payload.Name
	u.Email = payload.Email
	return nil

}

方法二

//使用第三方套件:copier.Copy轉換
func toUserBriefCopier(to *UserBrief, from *UserDetail) error {

	//Copy(toValue interface{}, fromValue interface{})
	err := copier.Copy(to, from)
	if err != nil {
		return err
	}
	return nil
}

方法三 : 使用SandardJson

但使用這方法要注意效能問題,也有其他easyJson,fastJson可替換.

func ToUserSandardJsonMarshal(to *UserBrief, from *UserDetail) error {
	b, err := json.Marshal(from)
	if err != nil {
		return errors.Wrap(err, "marshal from data err")
	}

	err = json.Unmarshal(b, to)
	if err != nil {
		return errors.Wrap(err, "unmarshal to data err")
	}

	return nil
}

參考

Last updated