티스토리 뷰

반응형

Photo by Alain Pham on Unsplash

 

구조체를 정의하고 사용하고 있었는데 특정 필드의 타입이 변경이 된다면 어떻게 데이터를 옮길 있을까?

두가지 사례로 실제 코드를 통해 이해해 본다

 

 

TL;DR: 기존 구조체 인스턴스를 marshal해서 새로운 구조체 인스턴스로 unmarshaling 해주면, 타입이 달라 충돌이 나는 필드를 제외하고는 가져올 있ㄷ.

 

사례1. string to []string

 

Playground: https://play.golang.org/p/erJmWKSowPy

 

Foo 구조체 인스턴스를 Bar 구조체 인스턴스로 옮기려 한다.

여기서는 필드가 뿐이지만, 필드가 많다면 하나씩 일일이 옮기기 번거롭고 실수를 있다.

 

// from
type Foo struct {
	Id   string `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// to
type Bar struct {
	Id   string   `json:"id"`
	Name []string `json:"name"`
	Age  int      `json:"age"`
}

그냥 다짜고짜 foo 직렬화 - marshalling 해준 다음, bar unmarshalling 해주면 된다.

 

func main() {
	foo := Foo{Id: "123", Name: "Joe", Age: 35}
	b, err := json.Marshal(foo)
	if err != nil {
		panic(err)
	}
	fmt.Println("foo marshalled: ", string(b))

	var bar Bar
	fmt.Printf("bar initialized: %+v\n", bar)
	if err := json.Unmarshal(b, &bar); err != nil {
		fmt.Println("incomplete unmarshal: ", err)
	}
	fmt.Printf("unmarshalled to bar: %+v\n", bar)
	bar.Name = make([]string, 1)
	bar.Name[0] = foo.Name
	fmt.Printf("foo to bar migrated: %+v\n", bar)
}

 

이때 unmarshaling 중에 아래와 같이 에러가 발생하지만 이걸 무시해주고 진행하는 것이다.

 

json: cannot unmarshal string into Go struct field Bar.name of type []string

 

결과는 아래와 같다.

foo marshalled:  {"id":"123","name":"Joe","age":35}
bar initialized: {Id: Name:[] Age:0}
incomplete unmarshal:  json: cannot unmarshal string into Go struct field Bar.name of type []string
unmarshalled to bar: {Id:123 Name:[] Age:35}
foo to bar migrated: {Id:123 Name:[Joe] Age:35}

 

사례2. string to int

 

Playground: https://play.golang.org/p/OneEKm9oV5N

 

이번에는 string이었던 필드 하나가 int 바뀐 것이다.

 

// from
type Foo struct {
	Id  string `json:"id"`
	Age string `json:"age"`
}

// to
type Bar struct {
	Id  string `json:"id"`
	Age int    `json:"age"`
}

 

모두 동일하다. marshal 다음 unmarshal하면 type 맞는 필드들은 그대로 값이 전달된다.

에러는 나지만 무시하면 되고, type 맞지 않는 필드만 수동으로 복사해주는 것이다.

 

func main() {
	foo := Foo{Id: "123", Age: "25"}
	b, err := json.Marshal(foo)
	if err != nil {
		panic(err)
	}
	fmt.Println("foo marshalled: ", string(b))

	var bar Bar
	fmt.Printf("bar initialized: %+v\n", bar)
	if err := json.Unmarshal(b, &bar); err != nil {
		fmt.Println("incomplete unmarshal: ", err)
	}
	fmt.Printf("unmarshalled to bar: %+v\n", bar)
	age, err := strconv.Atoi(foo.Age)
	if err != nil {
		panic(err)
	}
	bar.Age = age
	fmt.Printf("foo to bar migrated: %+v\n", bar)
}

 

에러는 나지만 무시하면 되고, type 맞지 않는 필드만 수동으로 복사해주는 것이다.

 

foo marshalled:  {"id":"123","age":"25"}
bar initialized: {Id: Age:0}
incomplete unmarshal:  json: cannot unmarshal string into Go struct field Bar.age of type int
unmarshalled to bar: {Id:123 Age:0}
foo to bar migrated: {Id:123 Age:25}

 

 

반응형
댓글
댓글쓰기 폼