使用Go递归在数组中累加/附加值的问题

时间:2018-11-19 22:10:57

标签: arrays go

首先,这是我第一个使用Go的非虚拟程序。任何建议将不胜感激。

代码说明:

我想从正在分页信息的API检索所有信息。所以我想遍历所有页面以获得所有信息。

这是我到目前为止所做的:

我具有以下两个功能:

func request(requestData *RequestData) []*ProjectsResponse {

    client := &http.Client{
        Timeout: time.Second * 10,
    }

    projects := []*ProjectsResponse{}
    innerRequest(client, requestData.URL, projects)

    return projects
}

func innerRequest(client *http.Client, URL string, projects []*ProjectsResponse) {

    if URL == "" {
        return
    }

    req, err := http.NewRequest("GET", URL, nil)
    if err != nil {
        log.Printf("Request creation failed with error %s\n", err)
    }
    req.Header.Add("Private-Token", os.Getenv("API_KEY"))

    res, err := client.Do(req)
    log.Printf("Executing request: %s", req.URL)

    if err != nil {
        log.Printf("The HTTP request failed with error %s\n", err)
    }
    data, _ := ioutil.ReadAll(res.Body)
    var response ProjectsResponse
    err = json.Unmarshal(data, &response)

    if err != nil {
        log.Printf("Unmarshalling failed with error %s\n", err)
    }

    projects = append(projects, &response)
    pagingData := getPageInformation(res)
    innerRequest(client, pagingData.NextLink, projects)
}

不良行为:

projects []*ProjectsResponse数组中的值将附加到递归的每次迭代中,但是当递归结束时,我得到一个空数组列表。因此,在innerRequests结束后,在project方法内的request变量中,我什么也没得到。

希望有人发现我的错误。 提前致谢。

2 个答案:

答案 0 :(得分:1)

混淆在于Go中处理slice的方式。 Here是深入的解释,但我将其缩写。

常见的误解是您传递的slice是对slice引用,这是错误的。在处理切片时所操作的实际变量称为 slice标头。这是一个简单的struct,其引用是对幕后的底层数组的引用,并遵循Go的按值传递规则,即它已被复制传递给函数时。因此,如果不返回,则不会有更新的标头。

从递归返回数据遵循简单的模式。这是一个基本的例子。我还提供了一个不需要退货但可以在切片上作为参考进行操作的版本,它将修改原始版本。 (注意:通常不认为绕过切片指针是惯用的Go)

游乐场链接:https://play.golang.org/p/v5XeYpH1VlF

// correct way to return from recursion
func addReturn(s []int) []int {
    if finalCondition(s) {
        return s
    }
    s = append(s, 1)
    return addReturn(s)
}

// using a reference
func addReference(s *[]int) {
    if finalCondition(*s) {
        return
    }
    *s = append(*s, 1)
    addReference(s)
}

// whatever terminates the recursion
func finalCondition(s []int) bool {
    if len(s) >= 10 {
        return true
    }
    return false
}

答案 1 :(得分:1)

我猜您所有的项目对象都作用于函数,因此当函数结束时它们不再存在。我认为在调用innerRequest之前不需要存在您的项目,因此您可能只应使用该方法返回项目。我认为类似的东西应该可以工作...

func innerRequest(client *http.Client, URL string) []*ProjectsResponse {

if URL == "" {
    return nil
}

//More code...

pagingData := getPageInformation(res)
return append([]*ProjectsResponse{&response}, innerRequest(client, pagingData.NextLink)...)
}