将 `struct` 作为类型名称传递给函数参数
Pass `struct` as type name to function argument
我正在用 go 编写某种基于 RESTfull API 的对象关系映射器。
当我完成它时,我计划让它获得麻省理工学院的许可。
这个想法是使用一些第 3 方 REST API 作为数据存储,golang
客户端将查询它以获取所需的数据。
API 响应是 JSON 具有已知结构的响应。
这是我的代码:
type AClient struct {
Id string `json:"id"`
Uid string `json:"uid"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
City string `json:"city"`
Address string `json:"address"`
Telefone string `json:"telefone"`
Zip string `json:"zip"`
Telefon string `json:"telefon"`
Comment string `json:"comment"`
}
type AEvents struct {
Id string `json:"id"`
Security bool `json:"security"`
Description string `json:"description"`
Good AGood `json:"good"`
Client AClient `json:"client"`
Author AAuthor `json:"author"`
InFuture bool `json:"inFuture"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type Entry struct {
AEvents //this have to be changed to `AClients` in runtime when needed
}
type ORM struct {
ApiUrl string
ModelName string
ModelInterface Entry
HuntKey string
HuntSid string
Csrf string
}
func (o *ORM) Query(parameters map[string]string) ([]Entry, AMetadata, error) {
responseParsed := struct {
Status string `json:"status"`
Metadata AMetadata `json:"metadata"`
Data []Entry `json:"data"` //todo - use o.ModelInterface
}{}
client := &http.Client{}
var queryString string
for k, v := range parameters {
queryString = queryString + fmt.Sprintf("%v=%v&", url.QueryEscape(k), url.QueryEscape(v))
}
req, err := http.NewRequest("GET", fmt.Sprintf("%v%v?%v", o.ApiUrl, o.ModelName, queryString), nil)
fmt.Println("---------------------------------------------")
fmt.Println(fmt.Sprintf("[GET] %v%v?%v", o.ApiUrl, o.ModelName, queryString))
req.Header.Set("huntKey", o.HuntKey)
if err != nil {
return nil, AMetadata{}, err
}
res, err1 := client.Do(req)
defer res.Body.Close()
if err1 != nil {
return nil, AMetadata{}, err1
}
if res.StatusCode == 200 {
for _, v := range res.Cookies() {
if v.Name == "XSRF-TOKEN" {
o.Csrf = v.Value
}
if v.Name == "hunt.sid" {
o.HuntSid = v.Value
}
}
fmt.Printf("CSRF %v\n", o.Csrf)
fmt.Printf("HuntSid %v\n", o.HuntSid)
fmt.Println("---------------------------------------------")
raw, err2 := ioutil.ReadAll(res.Body)
if err2 != nil {
return nil, AMetadata{}, err2
} else {
err2 = json.Unmarshal(raw, &responseParsed)
return responseParsed.Data, responseParsed.Metadata, nil
}
} else {
return nil, AMetadata{}, errors.New("Unable to fetch data!")
}
}
我该怎么做:
实例化 ORM
对象时,我如何传递将用于解析 JSON 响应的结构名称。当前代码适用于 AEvents
的 struct
,但我希望它可以轻松更改 AClient
等等。
更新:
我查看了 https://github.com/jinzhu/gorm 的代码,发现了很多我如何实现它的东西。
然后,正如我所承诺的,我将此代码作为开源发布 -https://github.com/vodolaz095/hrorm
您可以使用反射,但请注意它非常重要且相对较慢。不知道还有什么办法。
执行此操作的最简单方法是使参数类型为 interface{}
并传入一个空的(未初始化的)实例,该实例是您希望解组的结构。我强烈建议阅读我列出的两个链接中的第二个 - 它清楚地介绍了反射以及如何使用它来解决此类问题。
我正在用 go 编写某种基于 RESTfull API 的对象关系映射器。
当我完成它时,我计划让它获得麻省理工学院的许可。
这个想法是使用一些第 3 方 REST API 作为数据存储,golang
客户端将查询它以获取所需的数据。
API 响应是 JSON 具有已知结构的响应。
这是我的代码:
type AClient struct {
Id string `json:"id"`
Uid string `json:"uid"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
City string `json:"city"`
Address string `json:"address"`
Telefone string `json:"telefone"`
Zip string `json:"zip"`
Telefon string `json:"telefon"`
Comment string `json:"comment"`
}
type AEvents struct {
Id string `json:"id"`
Security bool `json:"security"`
Description string `json:"description"`
Good AGood `json:"good"`
Client AClient `json:"client"`
Author AAuthor `json:"author"`
InFuture bool `json:"inFuture"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type Entry struct {
AEvents //this have to be changed to `AClients` in runtime when needed
}
type ORM struct {
ApiUrl string
ModelName string
ModelInterface Entry
HuntKey string
HuntSid string
Csrf string
}
func (o *ORM) Query(parameters map[string]string) ([]Entry, AMetadata, error) {
responseParsed := struct {
Status string `json:"status"`
Metadata AMetadata `json:"metadata"`
Data []Entry `json:"data"` //todo - use o.ModelInterface
}{}
client := &http.Client{}
var queryString string
for k, v := range parameters {
queryString = queryString + fmt.Sprintf("%v=%v&", url.QueryEscape(k), url.QueryEscape(v))
}
req, err := http.NewRequest("GET", fmt.Sprintf("%v%v?%v", o.ApiUrl, o.ModelName, queryString), nil)
fmt.Println("---------------------------------------------")
fmt.Println(fmt.Sprintf("[GET] %v%v?%v", o.ApiUrl, o.ModelName, queryString))
req.Header.Set("huntKey", o.HuntKey)
if err != nil {
return nil, AMetadata{}, err
}
res, err1 := client.Do(req)
defer res.Body.Close()
if err1 != nil {
return nil, AMetadata{}, err1
}
if res.StatusCode == 200 {
for _, v := range res.Cookies() {
if v.Name == "XSRF-TOKEN" {
o.Csrf = v.Value
}
if v.Name == "hunt.sid" {
o.HuntSid = v.Value
}
}
fmt.Printf("CSRF %v\n", o.Csrf)
fmt.Printf("HuntSid %v\n", o.HuntSid)
fmt.Println("---------------------------------------------")
raw, err2 := ioutil.ReadAll(res.Body)
if err2 != nil {
return nil, AMetadata{}, err2
} else {
err2 = json.Unmarshal(raw, &responseParsed)
return responseParsed.Data, responseParsed.Metadata, nil
}
} else {
return nil, AMetadata{}, errors.New("Unable to fetch data!")
}
}
我该怎么做:
实例化 ORM
对象时,我如何传递将用于解析 JSON 响应的结构名称。当前代码适用于 AEvents
的 struct
,但我希望它可以轻松更改 AClient
等等。
更新: 我查看了 https://github.com/jinzhu/gorm 的代码,发现了很多我如何实现它的东西。 然后,正如我所承诺的,我将此代码作为开源发布 -https://github.com/vodolaz095/hrorm
您可以使用反射,但请注意它非常重要且相对较慢。不知道还有什么办法。
执行此操作的最简单方法是使参数类型为 interface{}
并传入一个空的(未初始化的)实例,该实例是您希望解组的结构。我强烈建议阅读我列出的两个链接中的第二个 - 它清楚地介绍了反射以及如何使用它来解决此类问题。