Search code examples
gogo-generate

Go generate only scans main.go


I am having some trouble using go generate to generate a grpc server when running go generate from the root of my project directory.

When I run go generate -v it only returns main.go. However, the directives are defined in one the subpackages. If I run go generate in the sub package it works as expected. I expected the imports to ensure that go generate would find the subpackages and run the directives.

The project has the following structure:

cmd/
  root.go
  run.go
pkg/
  subpkg/
    protobuf/
      proto1.proto
    subpkg.go
main.go

Contents of subpkg.go

//go:generate protoc -I ./protobuf --go_out=plugins=grpc:./protobuf ./protobuf/proto1.proto
package subpkg

Contents of main.go:

package main

import (
    "fmt"
    "os"

    "my-project/cmd"
)

func main() {
    if err := cmd.RootCommand.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

In the run.go package, I import the package subpkg.

How do I ensure go generate can be run from the root of the project and execute all directives in all sub packages.


Solution

  • You're looking for go generate ./....

    Per go help generate:

    usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]
    
    ...
    
    For more about specifying packages, see 'go help packages'.
    

    go help packages:

    Many commands apply to a set of packages:
    
    go action [packages]
    
    Usually, [packages] is a list of import paths.
    
    An import path that is a rooted path or that begins with
    a . or .. element is interpreted as a file system path and
    denotes the package in that directory.
    
    Otherwise, the import path P denotes the package found in
    the directory DIR/src/P for some DIR listed in the GOPATH
    environment variable (For more details see: 'go help gopath').
    
    If no import paths are given, the action applies to the
    package in the current directory.
    
    ...
    
    An import path is a pattern if it includes one or more "..." wildcards,
    each of which can match any string, including the empty string and
    strings containing slashes. Such a pattern expands to all package
    directories found in the GOPATH trees with names matching the
    patterns.
    

    So, when you don't specify a package to a Go command that takes one, it assumes the package is the current directory. Subdirectories are different packages, so they aren't included. A handy shorthand for "this package and all packages in sudirectories underneath it recursively" is ./..., as in

    go get ./...
    go generate ./...
    go test ./...