如何使函数接受字符串参数,并根据它返回不同的结构类型?

I want to create a function that takes string argument, and depending of string returns different types

In my current project I am using Go version 1.11.4 for Rest API, PostgreSQL 11 for storing data. The function is for avoiding the code redundancy, I just need one function for handling the requests, whithout this function I would be write more many request handlers.

Functions is:

func GetArrayOfModelStructs(table_name string) interface{} {
    if table_name == "prefs_n_cities" {
        Prefs_n_cities_array := &models.Prefs_n_cities_array{}
        return Prefs_n_cities_array
    } else if table_name == "position_owner" {
        Position_owners := &models.Position_owners{}
        return Position_owners
    } else if table_name == "region" {
        Regions := &models.Regions{}
        return Regions
    } else if table_name == "district" {
        Districts := &models.Districts{}
        return Districts
    } else if table_name == "locality" {
        Localities := &models.Localities{}
        return Localities
    } else if table_name == "locality_type" {
        Locality_types := &models.Locality_types{}
        return Locality_types
    } else if table_name == "population" {
        Populations := &models.Populations{}
        return Populations
    }
    return nil
}
func GetModelStructs(table_name string) interface{} {
    if table_name == "prefs_n_cities" {
        return models.Prefs_n_cities{}
    } else if table_name == "position_owner" {
        return models.Position_owner{}
    } else if table_name == "region" {
        return models.Regions{}
    } else if table_name == "district" {
        return models.District{}
    } else if table_name == "locality" {
        return models.Locality{}
    } else if table_name == "locality_type" {
        return models.Locality_type{}
    } else if table_name == "population" {
        return models.Population{}
    }
    return nil
}

My structs example like:

type Prefs_n_cities struct {
    id          int32
    Name        string
    Description string
    Region_id   int32
}

type Prefs_n_cities_array struct {
    Array []Prefs_n_cities
}

And all of this I trying to use in another package for handling requests:

var GetData = func(res http.ResponseWriter, req *http.Request) {
    // u.Logging(req, false)
    db_name := req.URL.Query().Get("table_name")

    data := u.GetArrayOfModelStructs(db_name)

    spew.Dump(data)

    sqlString := `SELECT * FROM "new_rollout_managment".` + db_name

    rows, err := database.DB.Query(sqlString)
    if err != nil {
        http.Error(res, err.Error(), 400)
        return
    }
    defer rows.Close()

    for rows.Next() {
        model := u.GetModelStructs(db_name)
        err = rows.Scan(&model)
        if err != nil {
            http.Error(res, err.Error(), 400)
            return
        }
        data.Array = append(data.Array, model)
    }
    err = rows.Err()
    if err != nil {
        http.Error(res, err.Error(), 400)
        return
    }

    out, err := json.Marshal(models)
    if err != nil {
        http.Error(res, err.Error(), 500)
        return
    }

    resp := u.Message(true, "Array of dictionaries")
    resp["Dictionaries"] = out

    u.Respond(res, resp)
}

My router is:

func Use(router *mux.Router) {

    router.HandleFunc("/api/test/new", controllers.TestFunc).Methods("POST")
    router.HandleFunc("/api/dictionaries/getdata", controllers.GetData).Methods("GET")
}

But in the GetData handler I have an error:

data.Array undefined (type interface {} is interface with no methods)

You can't do that. But you have two options:

  1. Return an interface{}, as you are doing, then convert to a concrete type. This probably defeats your purpose.

  2. Pass in your destination as a pointer, and modify it in place. So something like:

    func GetArrayOfModelStructs(table_name string, dst interface{}) error {
    

    Then have your function put the value in dst. This does require that the value passed as dst is a pointer. This is a very common pattern, seen in json.Unmarshal(), in sql's Rows.Scan, and many other places in the standard library and elsewhere.