encoding/json 패키지 쓰다보니 커스텀 자료형을 인코딩/디코딩할 일이 생겨서 질문드립니다.


커스텀 자료형을 다룰 때 보통 하는 말이 해당 자료형에 대한 json.Marshler와 json.Unmarshler 인터페이스를 구현하라고 하거든요.


type Marshaler interface {

        MarshalJSON() ([]byte, error)

}


type Unmarshaler interface {

        UnmarshalJSON([]byte) error

}


그러면 제 생각에는 해당 자료형을 MYTYPE이라치면


func (t MYTYPE) MarshalJSON() ([]byte, error)

func (t MYTYPE) UnmarshalJSON([]byte) error


이렇게 구현해야할 것 같고요.

그런데 UnmarshalJSON을 MYTYPE이 아닌 *MYTYPE에 대해 구현하더라고요


func (t MYTYPE) MarshalJSON() ([]byte, error)

func (t *MYTYPE) UnmarshalJSON([]byte) error


그러면 이건 MYTYPE이 Marshaler와 Unmarshaler 모두를 구현한게 아니라

MYTYPE이 Marshaler를, *MYTPE이 Unmarshaler를 각각 구현한 것 아닌가요?


물론 이렇게 함수를 구현해도 MYTYPE이 MarshalJSON, UnmarshalJSON 메소드를 사용할 수 있다는 것은 압니다.

그리고 UnmarshalJSON은 *MYTYPE에 대해서 구현해야 MYTYPE 자료형의 변수 내용물을 변경할 수 있다는 것도 알고요.

그럼에도 인터페이스 구현과 메소드 사용 가능은 포함 범위가 다른 이야기라 의아해서 질문드립니다.


제 생각에는 해당 타입이 Marshaler를, 해당 타입의 포인터 타입이 Unmarshaler를 구현해야 한다...라는 말이 복잡해서 대충 말하는 거 아닌가 싶기도 한데 어떤지요?





참고)


package main


import "fmt"


type MYPRINTER interface {

    PrintOnce()

    PrintTwice()

}


type MYTYPE string


func (s MYTYPE) PrintOnce() {

    fmt.Println(string(s))

}


func (s *MYTYPE) PrintTwice() {

    fmt.Println(string(*s))

    fmt.Println(string(*s))

}


func main() {

    var s MYTYPE = "Hello, world!"


    s.PrintOnce()  // no error

    s.PrintTwice() // no error


    // var p MYPRINTER = s // error, MYTYPE does not implement MYPRINTER (PrintTwice method has pointer receiver)

}