liveBook · Manning

Retry

As explained in Go in Practice, Second Edition

A retry is a repeated attempt to perform an operation after a failure, typically to recover from a transient problem.

Retry repeats a failed network operation when the failure may be temporary. For HTTP connections, detect timeout conditions, retry while attempts remain, and otherwise return the error for logging or alerting. section 11.1.2

A practical retry implementation combines failure detection with bounded recovery:

  • Check errors from net, http, and url operations for recognized timeout cases, including wrapped errors and closed network connections. section 11.1.2
  • Retry only while a retry count remains, decrementing the count on each recursive download attempt. section 11.1.2
  • Resume a partially written download by setting an HTTP Range header from the existing file size. section 11.1.2
  • Use an HTTP client timeout and return non-timeout errors without treating them as retryable failures. section 11.1.2
Listing 11.5 Download with retries
func download(location string, file *os.File, retries int64) error {
     req, err := http.NewRequest("GET", location, nil)   #1
     if err != nil {
            return err
     }
     fi, err := file.Stat()   #2
     if err != nil { #4
            return err #4
     } #4
     current := fi.Size()   #3
     if current > 0 {                                    #4
            start := strconv.FormatInt(current, 10)      #4
            req.Header.Set("Range", "bytes="+start+"-")  #4
     }                                                   #4
     cc := &http.Client{Timeout: 5 * time.Minute}   #5
     res, err := cc.Do(req)   #6
     if err != nil && hasTimedOut(err) {                #7
            if retries > 0 {                           
                   return download(location, file, 
                   retries-1)                            
            }                                          
            return err                                 
     } else if err != nil {
            return err
     }
     if res.StatusCode < 200 || res.StatusCode > 300 {   #8
            errFmt := "Unsuccess HTTP request. Status
            : %s"                                       
            return fmt.Errorf(errFmt, res.Status)       
     }
     if res.Header.Get("Accept-Ranges") != "bytes" {   #9
            retries = 0                                #9
     }                                                 #9
     _, err = io.Copy(file, res.Body)    #10
     if err != nil && hasTimedOut(err) {                 #11
            if retries > 0 {                            
                   return download(location, file, 
                   retries-1)                             
            }                                           
            return err                                  
     } else if err != nil {
            return err
     }
     return nil
}

Shows a Go download function that creates a request, resumes from the current file size, applies a client timeout, and retries detected timeouts. section 11.1.2

How Go in Practice, Second Edition covers it

How deep it goes
Explains timeout classification, resumable downloads, client timeouts, and recursive retry control, but not broader backoff policies.
Examples
Demonstrates timeout classification and a resumable file download using Go's HTTP client and Range requests.
What it assumes
Assumes familiarity with Go errors, files, HTTP requests, and response handling while clarifying several timeout error forms.
What you can do after
Build a bounded, timeout-aware Go download retry using standard HTTP requests and partial-file resumption.
How it connects
Connects retries with HTTP, network timeouts, error handling, REST responses, and gRPC service reliability.

Also explained in

Compare how 21 books explain retry →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Practice, Second Edition. The section links point to the parts of the book it draws on.