> For the complete documentation index, see [llms.txt](https://minilabmemo.gitbook.io/golang-memo/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://minilabmemo.gitbook.io/golang-memo/basic/go-basic/bu-tong-jie-gou-zhuan-huan.md).

# 不同結構轉換

不同結構轉轉後換

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

```go

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

}
```

#### 方法一

```go
//方式一：自己寫轉換 一個欄位一個欄位對應
//缺點：如果欄位太多會寫到懷疑自己，而且容易漏
//優點 ： 性能較好，可以自己處理錯誤訊息
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

}
```

方法二

```go
//使用第三方套件：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可替換．

```go
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
}

```

參考

| ref                                                                |
| ------------------------------------------------------------------ |
| [Golang如何优雅的转换两个相似的结构体？](https://www.zhihu.com/question/449267385) |
|                                                                    |
