如何让这段 Go 代码更 DRY?
How do I make this Go code more DRY?
我正在为 REST API 实现一个 Go 包装器。它基本上解析 JSON 并且应该 return 适当的结构类型。我发现自己经常这样做:
// GetBlueprintDetails returns details about a blueprint
func (c *Client) GetBlueprintDetails(projectID string, blueprintID string) (*BlueprintDetails, *APIError) {
path := fmt.Sprintf("projects/%s/blueprints/%s", projectID, blueprintID)
res, err := c.Request("GET", path, nil, nil)
if err != nil {
return nil, err
}
var ret BlueprintDetails
e := json.Unmarshal(res.Body, &ret)
if e != nil {
return nil, &APIError{Error: &e}
}
return &ret, nil
}
// GetProjects returns a list of projects for the user
func (c *Client) GetProjects() (*[]Project, *APIError) {
res, err := c.Request("GET", "projects", nil, nil)
if err != nil {
return nil, err
}
var ret []Project
e := json.Unmarshal(res.Body, &ret)
if e != nil {
return nil, &APIError{Error: &e}
}
return &ret, nil
}
这两个函数之间的唯一区别基本上是解组结构的类型。我知道 Go 中没有泛型,但必须有一种模式才能使它更 DRY。
有什么想法吗?
您可以创建一个 MakeRequest
函数来执行 http 请求部分并将 json 解组为结构
这是你可以做的,看看MakeRequest
函数
// GetBlueprintDetails returns details about a blueprint
func (c *Client) GetBlueprintDetails(projectID string, blueprintID string) (*BlueprintDetails, *APIError) {
path := fmt.Sprintf("projects/%s/blueprints/%s", projectID, blueprintID)
bluePrintDetails = new(BlueprintDetails)
err := c.MakeRequest("GET", path, bluePrintDetails)
return bluePrintDetails, err
}
// GetProjects returns a list of projects for the user
func (c *Client) GetProjects() (*[]Project, *APIError) {
projects = make([]Project, 0)
err := c.MakeRequest("GET", "project", &projects)
return &projects, err
}
func (c *Client) MakeRequest(method string, path string, response interface{}) *APIError {
res, err := c.Request(method, path, nil, nil)
if err != nil {
return nil, err
}
e := json.Unmarshal(res.Body, response)
if e != nil {
return &APIError{Error: &e}
}
return nil
}
我正在为 REST API 实现一个 Go 包装器。它基本上解析 JSON 并且应该 return 适当的结构类型。我发现自己经常这样做:
// GetBlueprintDetails returns details about a blueprint
func (c *Client) GetBlueprintDetails(projectID string, blueprintID string) (*BlueprintDetails, *APIError) {
path := fmt.Sprintf("projects/%s/blueprints/%s", projectID, blueprintID)
res, err := c.Request("GET", path, nil, nil)
if err != nil {
return nil, err
}
var ret BlueprintDetails
e := json.Unmarshal(res.Body, &ret)
if e != nil {
return nil, &APIError{Error: &e}
}
return &ret, nil
}
// GetProjects returns a list of projects for the user
func (c *Client) GetProjects() (*[]Project, *APIError) {
res, err := c.Request("GET", "projects", nil, nil)
if err != nil {
return nil, err
}
var ret []Project
e := json.Unmarshal(res.Body, &ret)
if e != nil {
return nil, &APIError{Error: &e}
}
return &ret, nil
}
这两个函数之间的唯一区别基本上是解组结构的类型。我知道 Go 中没有泛型,但必须有一种模式才能使它更 DRY。
有什么想法吗?
您可以创建一个 MakeRequest
函数来执行 http 请求部分并将 json 解组为结构
这是你可以做的,看看MakeRequest
函数
// GetBlueprintDetails returns details about a blueprint
func (c *Client) GetBlueprintDetails(projectID string, blueprintID string) (*BlueprintDetails, *APIError) {
path := fmt.Sprintf("projects/%s/blueprints/%s", projectID, blueprintID)
bluePrintDetails = new(BlueprintDetails)
err := c.MakeRequest("GET", path, bluePrintDetails)
return bluePrintDetails, err
}
// GetProjects returns a list of projects for the user
func (c *Client) GetProjects() (*[]Project, *APIError) {
projects = make([]Project, 0)
err := c.MakeRequest("GET", "project", &projects)
return &projects, err
}
func (c *Client) MakeRequest(method string, path string, response interface{}) *APIError {
res, err := c.Request(method, path, nil, nil)
if err != nil {
return nil, err
}
e := json.Unmarshal(res.Body, response)
if e != nil {
return &APIError{Error: &e}
}
return nil
}