2013-10-09 3 views
8

가설 (다른 구조체의 구조체를 내장), I는 API를 실행하고 사용자가 사용자 리소스에 대한 GET 요청을 할 때, 나는 JSONGolang + MongoDB를 내장 유형

type User struct { 
    Id  bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"` 
    Name string  `json:"name,omitempty" bson:"name,omitempty"` 
    Secret string  `json:"-,omitempty" bson:"secret,omitempty"` 
} 

로 관련 필드를 반환합니다 보시다시피, 사용자의 비밀 필드는 json:"-"입니다. 이것은 대부분의 작업에서 내가 돌아오고 싶지 않다는 것을 의미합니다. 이 경우, 응답 필드 비밀 json:"-"로 반환되지 않습니다

{ 
    "id":1, 
    "Name": "John" 
} 

필드를 생략 할 것이다.

이제 암호 필드를 반환하려는 관리자 전용 경로를 엽니 다. 그러나 이는 User 구조체를 복제하는 것을 의미합니다.

내 현재 솔루션은 다음과 같습니다 : 관리 사용자로 사용자를 포함하는 방법이

type adminUser struct {  
    Id  bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"` 
    Name string  `json:"name,omitempty" bson:"name,omitempty"` 
    Secret string  `json:"secret,omitempty" bson:"secret,omitempty"` 
} 

있습니까? 상속의 종류 :

type adminUser struct {  
    User 
    Secret string  `json:"secret,omitempty" bson:"secret,omitempty"` 
} 

위의 경우 현재 작동하지 않습니다.이 경우 필드 암호 만 반환됩니다.

참고 : 실제 코드베이스에는 수십 개의 필드가 있습니다. 따라서 코드 복제 비용이 높습니다.

실제 몽고 쿼리

은 다음과 같습니다 :

func getUser(w http.ResponseWriter, r *http.Request) { 
    ....omitted code... 

    var user adminUser 
    err := common.GetDB(r).C("users").Find(
     bson.M{"_id": userId}, 
).One(&user) 
    if err != nil { 
     return 
    } 
    common.ServeJSON(w, &user) 
} 

답변

22

당신은 bson 패키지의 인라인 플래그 를 살펴 (즉 bson.Marshal 아래에 설명되어 있습니다)해야한다. 둘 다 adminUserUser 때문에이 구조, 와 데이터베이스에서 읽으려고 할 때 지금 당신은 당신이 중복 키 오류 을받을 것을 알 수 있습니다, 그러나

type adminUser struct { 
    User `bson:",inline"` 
    Secret string `json:"secret,omitempty" bson:"secret,omitempty"` 
} 

: 그것은 당신이 이런 일을 할 수 있도록해야한다 키는 secret입니다.

귀하의 경우에는 User 에서 Secret 필드를 제거하고 그 중 하나만 adminUser에 있습니다. secret 필드에 쓸 때마다 adminUser을 사용해야합니다.

+0

이 경우 런타임 오류가 발생합니다 : 내부 서버 오류 struct main.adminUser에 중복 키 'secret'이 있습니다! – samol

+0

내 대답이 업데이트되었습니다. 나는 중복 된 키가 있다는 것을 깨닫지 못했습니다. –

+1

레코드의 보조 노트와 마찬가지로 _ ", inline"_ 태그의 사용은 일반 필드 (비 포함/비 익명)에 대해서도 작동합니다. –

1

또 다른 대안은 인터페이스를 선언하는 것입니다.

type User struct { 
    Id  bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"` 
    Username string  `json:"username" bson:"username"` 
    Secret string  `json:"secret,omitempty" bson:"secret"` 
} 

func (u *User) SecureMe() { 
    u.Secret = "" 
} 

을 그리고 유일한 경로가 호출에 따라 호출 :

type SecureModel interface { 
    SecureMe() 
} 

은 모델을 구현해야합니다.

// I am being sent to a non-admin, secure me. 
if _, ok := user.(SecureModel); ok { 
    user.(SecureModel).SecureMe() 
} 
// Marshall to JSON, etc. 
... 

편집 : 여기서 인터페이스를 사용하는 이유는 일반적인 방법을 사용하여 임의의 모델을 유선으로 보낼 수있는 경우입니다.