Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reduce redundant code of duplicate function in Golang?

I have a Rest API application to list all json data to browser. as long as I have more modules my code is more redundant. and complex.

func UserList(w http.ResponseWriter, r *http.Request) {
    list := []models.User{}
    db.Find(&list)
    json.NewEncoder(w).Encode(list)
}

func ProductList(w http.ResponseWriter, r *http.Request) {
    list := []models.Product{}
    db.Find(&list)
    json.NewEncoder(w).Encode(list)
}

func OrderList(w http.ResponseWriter, r *http.Request) {
    list := []models.Order{}
    db.Find(&list)
    json.NewEncoder(w).Encode(list)
}

Is there any better solution to make this code into just one function Example

func List(w http.ResponseWriter, r *http.Request) {
    list := ??? List of struct here ???
    db.Find(&list)
    json.NewEncoder(w).Encode(list)
}
like image 610
Night Owl Avatar asked Dec 19 '25 21:12

Night Owl


2 Answers

you can do something like this:

func List(list interface{}, w http.ResponseWriter, r *http.Request,) {
    db.Find(list)
    json.NewEncoder(w).Encode(list)
}
like image 53
Umar Hayat Avatar answered Dec 21 '25 22:12

Umar Hayat


If you pass the model type as a request param, this should do it (including error handling):

func List(w http.ResponseWriter, r *http.Request) {
    var list interface{}
    switch r.FormValue("model") {
    case "user":
        list = new([]models.User)
    case "product":
        list = new([]models.Product)
    case "order":
        list = new([]models.Order)
    default:
        http.Error(w, "invalid type", http.StatusBadRequest)
        return
    }
    if err := db.Find(list); err != nil {
        http.Error(w, "db error", http.StatusInternalServerError)
        return
    }
    if err := json.NewEncoder(w).Encode(list); err != nil {
        log.Printf("json encoding error: %v", err)
    }
}

Another option is to build a registry of types, and even the slice creation can be factored out, using the help of reflect:

var reg = map[string]reflect.Type{
    "user":    reflect.TypeOf((*models.User)(nil)).Elem(),
    "product": reflect.TypeOf((*models.Product)(nil)).Elem(),
    "order":   reflect.TypeOf((*models.Order)(nil)).Elem(),
}

func List(w http.ResponseWriter, r *http.Request) {
    etype := reg[r.FormValue("model")]
    if etype == nil {
        http.Error(w, "invalid type", http.StatusBadRequest)
        return
    }

    list := reflect.New(reflect.SliceOf(etype)).Interface()
    if err := db.Find(list); err != nil {
        http.Error(w, "db error", http.StatusInternalServerError)
        return
    }
    if err := json.NewEncoder(w).Encode(list); err != nil {
        log.Printf("json encoding error: %v", err)
    }
}
like image 43
icza Avatar answered Dec 21 '25 23:12

icza



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!