Home > Software design >  Golang - embed.FS pass argument
Golang - embed.FS pass argument

Time:01-09

I need to modify fragment of code which needs to take argument instead of use hardcoded path in go:embed

My code:

package main

import (
    "embed"
    "log"
    
    "github.com/golang-migrate/migrate/v4/source/iofs"
)

// Instead of use hardcoded `migrations/*.sql` I need to pass 
// `path` to `migrations/*.sql` as a argument to `migrate` function
//go:embed migrations/*.sql
var fs embed.FS

func main() {
    const path = "migrations/*.sql"
    if err := migrate(path); err != nil {
        log.Fatal(err)
    }
    log.Println("done")
}

func migrate(path string) error {
    d, err := iofs.New(fs, "migrations")
    if err != nil {
        return err
    }
    
    // rest of the code...
    return nil
}

I already tried to use os.DirFS however result of this function only contains data with dir parameter without actual files from folder migrations/*.sql

CodePudding user response:

I'm not entirely sure I understand the question. You've created an embedded filesystem that contains multiple files (everything matching *.sql in the migrations directory). You can load files from this embedded filesystem by name.

Let's assume that your migrations directory looks like:

migrations/
├── bar.sql
└── foo.sql

Where foo.sql contains this is foo.sql, and similarly for bar.sql.

If we write code like this:

func main() {
  const path = "migrations/foo.sql"
  if err := migrate(path); err != nil {
    log.Fatal(err)
  }
  log.Println("done")
}

func migrate(path string) error {
  data, err := fs.ReadFile(path)
  if err != nil {
    panic(err)
  }

  fmt.Println(string(data))

  // rest of the code...
  return nil
}

You'd get the output:

this is foo.sql

If you want to iterate over files in your embedded filesystem, you can use the ReadDir method:

func main() {
  const path = "migrations"
  if err := migrate(path); err != nil {
    log.Fatal(err)
  }
  log.Println("done")
}

func migrate(path string) error {
  items, err := fs.ReadDir(path)
  if err != nil {
    panic(err)
  }

  for _, ent := range items {
    fmt.Println(ent.Name())
  }

  // rest of the code...
  return nil
}

This would print:

bar.sql
foo.sql

Does that help?

  •  Tags:  
  • go
  • Related