2017-03-26 1 views
0

구조체 조각을 함수로 전달하고 []interface{}으로 변환하여 채우고 함수 끝 작업 이후에 사용할 수 있습니까?함수의 인터페이스 슬라이스를 전달하고 해당 항목을 비 정렬 화합니다.

여기 https://play.golang.org/p/iPijsawEEg

가 짧은 설명 문제의 전체 예이다 :이 문제는 쉽게 단일 interface{} 대해 해결 될 수

type DBResponse struct { 
    Rows int    `json:"rows"` 
    Error string   `json:"error"` 
    Value json.RawMessage `json:"value"` 
} 
type User struct { 
    Id int `json:"id"` 
    Name string `json:"name"` 
} 

func loadDBRows(p []interface{}) { 
    var response DBResponse 
    someDataFromDB := []byte("{\"rows\":1, \"error\": \"\", \"value\": {\"name\":\"John\", \"id\":2}}") 
    json.Unmarshal(someDataFromDB, &response) 
    json.Unmarshal(response.Value, &p[0]) 
    fmt.Println(p)//p[0] filled with map, not object 
} 

func main() { 
    users := make([]User, 5) 
    data := make([]interface{}, 5) 
    for i := range users { 
     data[i] = users[i] 
    } 
    loadDBRows(data) 
} 

, U는 전체 예제에서 테스트 할 수있다. 왜 슬라이스로 해결할 수 없습니까?

나는 반영하지 않고 그것을하고 싶다! 선택된 데이터 구조체에 universal json 파서를 쓰는 "진정한 방법"이 있습니까 반영 및 매핑 [string] 인터페이스 {}없이? 복잡한 코드 및 추가 작업을 원하지 않음

도움에 감사드립니다! p 이후

답변

0

당신이 Userinterface{}하지에 대한 포인터를 전달하는 json.Unmarshal(response.Value, &p[0])이 라인에, 인터페이스의 한 조각이며, json.Unmarshal 데이터를 비 정렬 화하기 위해 할 수있는 대상으로 인터페이스를 수 있기 때문에, 그것은 아래에 보이지 않는 다른 유형은 interface{}이고 jsonmap으로 디코딩됩니다.

interface{}을 이미 콘크리트 유형에 대한 포인터로 사용하는 것입니다. data[i] = &users[i]&없이 interface{}을 전달하면 json.Unmarshal이됩니다.

func loadDBRows(p []interface{}) { 
    var response DBResponse 
    someDataFromDB := []byte("{\"rows\":1, \"error\": \"\", \"value\": {\"name\":\"John\", \"id\":2}}") 
    json.Unmarshal(someDataFromDB, &response) 
    json.Unmarshal(response.Value, p[0]) // notice the missing & 
    fmt.Println(p) 
} 

users := make([]User, 5) 
data := make([]interface{}, 5) 
for i := range users { 
    data[i] = &users[i] // notice the added & 
} 

https://play.golang.org/p/GEbIq9febY

+0

감사 alot을! 인터페이스 변환에 대해 더 읽어야합니다. 리소스를 조언 해 주시겠습니까? 다시 한 번 감사드립니다! –

+0

'json.Unmarshal'의 변환 규칙의 경우 [golang docs] (https://golang.org/pkg/encoding/json/#Unmarshal)를 읽고'interface {}'가 무엇인지 이해하는 것이 가장 좋습니다 좋은 기사를 찾을 수 있습니다 [여기] (https://research.swtch.com/interfaces) – mkopriva

+0

정말 고마워요! –

0

하나의 옵션은 슬라이스 요소에 액세스하기 위해 반영 패키지를 사용하는 것입니다. 이 같은

func loadDBRows(p interface{}) { 
    var response DBResponse 
    someDataFromDB := []byte("{\"rows\":1, \"error\": \"\", \"value\": {\"name\":\"John\", \"id\":2}}") 
    json.Unmarshal(someDataFromDB, &response) 
    v := reflect.ValueOf(p). // get reflect.Value for argument 
       Index(0). // get first element assuming that p is a slice 
       Addr().  // take address of the element 
       Interface() // get the pointer to element as an interface{} 
    json.Unmarshal(response.Value, v) 
} 

사용 loadDBRows :

기능은 p는 슬라이스 있다고 가정합니다. 질문과 []interface{}를 만들 필요가 없습니다 :

func main() { 
    users := make([]User, 5) 
    loadDBRows(users) 
    fmt.Println(users) 
} 

playground example

관련 문제