2013-07-06 66 views
1

我有以下功能:幹出我去功能與接口

func (r *Resource) Create(kind string, data io.ReadCloser) (err error) { 
    decoder := json.NewDecoder(data) 
    r.Kind = kind 

    switch kind { 
    case "user": 
    var user User 
    if err = decoder.Decode(&user); err != nil { 
     panic(err) 
    } 

    if err = user.Save(r.Context); err != nil { 
     panic(err) 
    } 

    r.Data = user 
    break 

    case "space": 
    var space Space 
    if err = decoder.Decode(&space); err != nil { 
     panic(err) 
    } 

    if err = space.Save(r.Context); err != nil { 
     panic(err) 
    } 

    r.Data = space 
    break 

    case "room": 
    var room Room 
    if err = decoder.Decode(&room); err != nil { 
     panic(err) 
    } 

    if err = room.Save(r.Context); err != nil { 
     panic(err) 
    } 

    r.Data = room 
    break 

    case "element": 
    var element Element 
    if err = decoder.Decode(&element); err != nil { 
     panic(err) 
    } 

    if err = element.Save(r.Context); err != nil { 
     panic(err) 
    } 

    r.Data = element 
    break 

    default: 
    break 
    } 
    return 
} 

正如你所看到的,在交換機的每個情況是,除了接收JSON數據的結構類型相同。

我懷疑在接口和類型聲明中有答案。

編輯:

我能夠打出來的部分保存到一個單獨的方法,但我仍然想不通沒有switch語句來解碼JSON對象到合適的結構的好辦法。

func (r *Resource) Create(kind string, data io.ReadCloser) (err error) { 
    decoder := json.NewDecoder(data) 
    r.Kind = kind 

    switch kind { 
    case "user": 
    var user User 
    if err = decoder.Decode(&user); err != nil { 
     panic(err) 
    } 
    r.saveEntity(&user) 
    break 

    case "space": 
    var space Space 
    if err = decoder.Decode(&space); err != nil { 
     panic(err) 
    } 
    r.saveEntity(&space) 
    break 

    case "room": 
    var room Room 
    if err = decoder.Decode(&room); err != nil { 
     panic(err) 
    } 
    r.saveEntity(&room) 
    break 

    case "element": 
    var element Element 
    if err = decoder.Decode(&element); err != nil { 
     panic(err) 
    } 
    r.saveEntity(&element) 
    break 

    default: 
    break 
    } 
    return 
} 

func (r *Resource) saveEntity(e Entity) { 
    if err := e.Save(r.Context); err != nil { 
    panic(err) 
    } 

    r.Data = e 
} 

回答

2

您可以移動實例化一個行功能,並創建映射 樣到相應的實例化功能的映射。其餘的代碼應該是可重用的。

實施例:

kinds := map[string]func() Entity { 
    "user": func() Entity { return &User{} }, 
    "space": func() Entity { return &Space{} }, 
    "room": func() Entity { return &Room{} }, 
} 

func Create(kind string) { 
    instance := kinds[kind]() 

    decoder.Decode(instance) 

    saveEntity(instance) 
}