Skip to content

Please add a non-internal API to read go.mod files #30147

Closed
@nim-nim

Description

@nim-nim

So starting with Go 1.11 we have go.mod module descriptor files, and it was recognized that the go command would not be the only one needing to manipulate those, so go help mod edit helpfully states

Edit provides a command-line interface for editing go.mod,
for use primarily by tools or scripts. It reads only go.mod;
it does not look up information about the modules involved.

Except the go.mod on-disk syntax is clearly one of a kind, so anyone actually needing to read go.mod in scripts will obviously use the -json flag to get something more regular.

And then, since it's hard to parse json in shell, the next step is obviously to use a json parsing lib in your favorite language and write some kind of helper. That language, for someone interested in parsing go module files, is likely to be go.

So you end up with things like:

  // Run “go help mod edit” on new go versions to get the current structure to parse
  // You may need to reorder the type declarations for the compiler to be happy
  type Module struct {
    Path    string
    Version string
  }

  type Require struct {
    Path     string
    Version  string
    Indirect bool
  }

  type Replace struct {
    Old Module
    New Module
  }

  type GoMod struct {
    Module  Module
    Go      string
    Require []Require
    Exclude []Module
    Replace []Replace
  }

  cmd := exec.Command("go", "mod", "edit", "-fmt", "-json")
  stdout, _ := cmd.StdoutPipe()
  cmd.Stderr = os.Stderr
  if err := cmd.Start(); err != nil {
                fmt.Fprintf(os.Stderr,"error invoking “go mod edit -fmt -json”, %v:\n", err)
    os.Exit(1)
        }
  var gomod GoMod
        if err := json.NewDecoder(stdout).Decode(&gomod); err != nil {
                fmt.Fprintf(os.Stderr,"error parsing “go mod edit -fmt -json”, %v\n", err)
    os.Exit(1)
        }

This is a pretty ridiculous way to access information the language already knows how to parse (and parse better). You need to redirect stderr to get any kind of error handling (and can not do anything about it unless you also parse the stderr messages).

Please just make it a function that takes a path as argument (default current dir) and
returns a GoMod object, with all the sanity checks of go mod edit -fmt -json

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions