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

时间:2019-01-30 07:37:49

标签: go

我想创建一个带有字符串参数的函数,并根据字符串返回不同的类型

在我当前的项目中,我将Go版本1.11.4用于Rest API,将PostgreSQL 11用于存储数据。 该函数是为了避免代码冗余,我只需要一个函数来处理请求,而没有这个函数,我将编写更多的请求处理程序。

功能是:

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
}

我的结构示例如下:

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

type Prefs_n_cities_array struct {
    Array []Prefs_n_cities
}

所有这些我都试图在另一个程序包中用于处理请求:

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)
}

我的路由器是:

func Use(router *mux.Router) {

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

但是在GetData处理程序中,我有一个错误:

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

1 个答案:

答案 0 :(得分:3)

您不能那样做。但是您有两个选择:

  1. 在执行操作时返回interface{},然后转换为具体类型。这可能会破坏您的目的。

  2. 将目的地作为指针传递,并就地进行修改。像这样:

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

    然后让您的函数将值放入dst中。这确实要求传递为dst的值是一个指针。这是一种非常常见的模式,在json.Unmarshal()sql's Rows.Scan以及标准库和其他地方的许多其他位置中都可以看到。