2016-02-26 9 views
12

Ich benutze Golang Revel für ein Webprojekt und ich mochte bisher 12 Projekte. In allen von ihnen habe ich eine Menge Code-Redundanz wegen der Rückgabetypen. Sehen Sie sich diese zwei Funktionen an:Wie man dynamische Struktur in Golang zurückgibt?

func (c Helper) Brands() []*models.Brand{ 

    //do some select on rethinkdb and populate correct model 
    var brands []*models.Brand 
    rows.All(&brands) 

    return brands 

} 

func (c Helper) BlogPosts() []*models.Post{ 

    //do some select on rethinkdb and populate correct model 
    var posts []*models.Post 
    rows.All(&posts) 

    return posts 

} 

Wie Sie sehen, sie beide die gleiche Art von Daten (Typ struct) zurückgibt. Meine Idee war, nur String var wie dies passieren:

func (c Helper) ReturnModels(modelName string) []*interface{} { 

    //do rethinkdb select with modelName and return []*interface{} for modelName 
} 

Mag ich nur ein Helfer-Typen für die Rückgabe Daten können statt gleiche Sache immer und immer wieder für verschiedene Modelle, aber gleichen Datentyp.

Meine Fragen sind:

  1. dies möglich bei allen
  2. Ist Wenn ja können Sie mich nach rechts docs Punkt
  3. Wenn nein, werde ich mehr als glücklich sein, Ihre Antwort zurück :)
+1

rechten Spur @ pregmatch +1 –

Antwort

14

Ja, es ist möglich, aber Ihre Funktion sollte interface{} und nicht []*interface zurückgeben.

func (c Helper) ReturnModels(modelName string) interface{} {} 

In diesem Fall könnten Sie Type Switches and/or Type Assertions verwenden den Rückgabewert zu werfen in seiner ursprünglichen Art ist.

Beispiel

Hinweis:

Playground

package main 

import "fmt" 

type Post struct { 
    Author string 
    Content string 
} 

type Brand struct { 
    Name string 
} 

var database map[string]interface{} 

func init() { 
    database = make(map[string]interface{}) 

    brands := make([]Brand, 2) 
    brands[0] = Brand{Name: "Gucci"} 
    brands[1] = Brand{Name: "LV"} 

    database["brands"] = brands 

    posts := make([]Post, 1) 
    posts[0] = Post{Author: "J.K.R", Content: "Whatever"} 

    database["posts"] = posts 
} 

func main() { 
    fmt.Println("List of Brands: ") 
    if brands, ok := ReturnModels("brands").([]Brand); ok { 
     fmt.Printf("%v", brands) 
    } 

    fmt.Println("\nList of Posts: ") 
    if posts, ok := ReturnModels("posts").([]Post); ok { 
     fmt.Printf("%v", posts) 
    } 

} 

func ReturnModels(modelName string) interface{} { 

    return database[modelName] 
} 
+0

: Ich habe Ihnen Revel, aber das folgende Snippet sollte nie eine allgemeine Vorstellung verwendet Können Sie Ihre Antwort ein wenig erweitern, wie? – OscarRyz

+1

Sie sind super! Ich werde deine Schuhe jederzeit strahlen :). Ich hasse es, wenn ich Redundanz habe, wenn ich nicht weiß, wie ich etwas tun soll. Was du geschrieben hast, hat gerade eine Menge Code aus meinen Projekten entfernt. – pregmatch

+2

Beachten Sie, dass 'ReturnModels (" Marken "). ([] Brand)' in Panik geraten, wenn die Typbestätigung fehlschlägt. In diesem Fall wäre es, wie Sie für '[] * models.Brand' behaupten sollten. Verwenden Sie das Komma, ok idiom, um vor Panik zu schützen: https://golang.org/doc/effective_go.html#interface_conversions – elithrar