go/build: ignore symlinks to directories when matching source files

Fixes #39841

Change-Id: Icbdc37d40e9c10179d6eb704d04482175b139f57
Reviewed-on: https://go-review.googlesource.com/c/go/+/240120
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
diff --git a/src/cmd/go/testdata/script/mod_symlink_dotgo.txt b/src/cmd/go/testdata/script/mod_symlink_dotgo.txt
new file mode 100644
index 0000000..d4cc143
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_symlink_dotgo.txt
@@ -0,0 +1,17 @@
+env GO111MODULE=on
+[!symlink] skip
+
+symlink dir.go -> dir
+
+# Issue #39841: symlinks to directories should be ignored, not treated as source files.
+go list -f '{{range .GoFiles}}{{.}}{{"\n"}}{{end}}' .
+stdout 'p\.go$'
+! stdout 'dir\.go$'
+
+-- go.mod --
+module example.com
+go 1.15
+-- p.go --
+package p
+-- dir/README.txt --
+This file exists to ensure that dir is a directory.
diff --git a/src/go/build/build.go b/src/go/build/build.go
index 4a5da30..39bc359 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -793,6 +793,12 @@
 		if d.IsDir() {
 			continue
 		}
+		if (d.Mode() & os.ModeSymlink) != 0 {
+			if fi, err := os.Stat(filepath.Join(p.Dir, d.Name())); err == nil && fi.IsDir() {
+				// Symlinks to directories are not source files.
+				continue
+			}
+		}
 
 		name := d.Name()
 		ext := nameExt(name)