如何杀死执行例程而不是通道?

I have a collection of job id's I must request data for. Each job id response could possibly return 3 pages. Once I have all the responses, I am extracting some props and writing it to a csv file.

I'd like to recursively call a function to get this data, should the response meta data indicate it is page 1 of x.

Once I have pages x of x I no longer wish to call that routine and when all routines have finished, I was to progress my application logic.

I am have been looking at go routines and channels as a way of handling this flow.

func (c *Controller) GetBulkJobProps() http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        jobs := models.BulkJobListIDs{}
        json.NewDecoder(r.Body).Decode(&jobs)

        if len(jobs.BulkSendJobs) == 0 {
            err := models.Error{}
            err.Message = "Missing bulk job id(s)"
            utils.SendError(w, 400, err)
            return
        }

        c := make(chan string)

        for _, id := range jobs.BulkSendJobs {
            go getLink(id, 1, c)
        }

        for l := range c {
            go func(id string) {

                if id == "quit" {
                    close(c)
                    return
                }

                getLink(id, 2, c)
            }(l)
        }

        filename := time.Now().Format("02-01-2006_15:04:05")

        utils.CreateCSV(filename, csvResponse)

        csvResponse = nil

        w.Header().Add("Content-Type", "application/json")
        utils.SendSuccess(w, nil)

    }
}

func getLink(id string, page int, c chan string) {
    data := utils.FetchBulkJobProps(id, page)

    for _, r := range data.SignatureRequests {
        for _, sr := range r.Signatures {
            csvResponse = append(csvResponse, []string{r.Title, sr.SignerEmailAddress, sr.StatusCode})
            if data.ListInfo.NumPages > data.ListInfo.Page {
                c <- id
                return
            }
            c <- "quit"
        }
    }
}

I was hoping that by ensuring data.ListInfo.NumPages > data.ListInfo.Page I can assert there is a next page to request, if not I would like to signal my channel to end this particular routine somehow.

I thought maybe by passing c <- "quit" back into the channel, rather than the id that needs a follow up call, I could signal my function literal to end that routine.

   for l := range c {
            go func(id string) {

                if id == "quit" {
                    close(c)
                    return
                }

                getLink(id, 2, c)
            }(l)
        }

Instead this appear to crash my app, I believe as I am now sending on a closed channel.