"io/ioutil"
        "os"
        "path/filepath"
+       "runtime"
        "strings"
        "sync"
+       "time"
 
        "cmd/go/internal/base"
        "cmd/go/internal/cache"
                if !cfg.BuildWork {
                        workdir := b.WorkDir
                        base.AtExit(func() {
-                               if err := os.RemoveAll(workdir); err != nil {
-                                       fmt.Fprintf(os.Stderr, "go: failed to remove work dir: %s\n", err)
+                               start := time.Now()
+                               for {
+                                       err := os.RemoveAll(workdir)
+                                       if err == nil {
+                                               return
+                                       }
+
+                                       // On some configurations of Windows, directories containing executable
+                                       // files may be locked for a while after the executable exits (perhaps
+                                       // due to antivirus scans?). It's probably worth a little extra latency
+                                       // on exit to avoid filling up the user's temporary directory with leaked
+                                       // files. (See golang.org/issue/30789.)
+                                       if runtime.GOOS != "windows" || time.Since(start) >= 500*time.Millisecond {
+                                               fmt.Fprintf(os.Stderr, "go: failed to remove work dir: %s\n", err)
+                                               return
+                                       }
+                                       time.Sleep(5 * time.Millisecond)
                                }
                        })
                }