# 不同結構轉換

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

```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) |
|                                                                    |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://minilabmemo.gitbook.io/golang-memo/basic/go-basic/bu-tong-jie-gou-zhuan-huan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
