docs/references/gofrcli/page.md
Managing repetitive tasks and maintaining consistency across large-scale applications is challenging!
GoFr CLI provides the following:
go version
To get started with GoFr CLI, use the below commands
go install gofr.dev/cli/gofr@latest
To check the installation:
gofr version
The CLI can be run directly from the terminal after installation. Here’s the general syntax:
gofr <subcommand> [flags]=[arguments]
initThe init command initializes a new GoFr project. It sets up the foundational structure for the project and generates a basic "Hello World!" program as a starting point. This allows developers to quickly dive into building their application with a ready-made structure.
gofr init
migrate createThe migrate create command generates a migration template file with pre-defined structure in your migrations directory. This boilerplate code helps you maintain consistent patterns when writing database schema modifications across your project.
gofr migrate create -name=<migration-name>
gofr migrate create -name=create_employee_table
This command generates a migration directory which has the below files:
20250127152047_create_employee_table.go) containing:package migrations
import (
"gofr.dev/pkg/gofr/migration"
)
func create_employee_table() migration.Migrate {
return migration.Migrate{
UP: func(d migration.Datasource) error {
// write your migrations here
return nil
},
}
}
// This is auto-generated file using 'gofr migrate' tool. DO NOT EDIT.
package migrations
import (
"gofr.dev/pkg/gofr/migration"
)
func All() map[int64]migration.Migrate {
return map[int64]migration.Migrate {
20250127152047: create_employee_table(),
}
}
💡 Best Practice: Learn about organizing migrations by feature to avoid creating one migration per table or operation.
wrap grpcgRPC Server
gofr wrap grpc server --proto=<path_to_the_proto_file>
Server
{serviceName}_gofr.go (auto-generated; do not modify){serviceName}_server.go (example structure below)gRPC Server
The command generates a server implementation template similar to this:
package server
import (
"gofr.dev/pkg/gofr"
)
// Register the gRPC service in your app using the following code in your main.go:
//
// service.Register{ServiceName}ServerWithGofr(app, &server.{ServiceName}Server{})
//
// {ServiceName}Server defines the gRPC server implementation.
// Customize the struct with required dependencies and fields as needed.
type {ServiceName}Server struct {
}
// Example method (actual methods will depend on your proto file)
func (s *MyServiceServer) MethodName(ctx *gofr.Context) (any, error) {
// Replace with actual logic if needed
return &ServiceResponse{
}, nil
}
For detailed instruction on setting up a gRPC server with GoFr see the gRPC Server Documentation
gRPC Client
gofr wrap grpc client --proto=<path_to_the_proto_file>
Client
{serviceName}_client.go (example structure below)Assuming the service is named hello, after generating the hello_client.go file, you can seamlessly register and access the gRPC service using the following steps:
type GreetHandler struct {
helloGRPCClient client.HelloGoFrClient
}
func NewGreetHandler(helloClient client.HelloGoFrClient) *GreetHandler {
return &GreetHandler{
helloGRPCClient: helloClient,
}
}
func (g GreetHandler) Hello(ctx *gofr.Context) (any, error) {
userName := ctx.Param("name")
helloResponse, err := g.helloGRPCClient.SayHello(ctx, &client.HelloRequest{Name: userName})
if err != nil {
return nil, err
}
return helloResponse, nil
}
func main() {
app := gofr.New()
// Create a gRPC client for the Hello service
helloGRPCClient, err := client.NewHelloGoFrClient(app.Config.Get("GRPC_SERVER_HOST"), app.Metrics())
if err != nil {
app.Logger().Errorf("Failed to create Hello gRPC client: %v", err)
return
}
greetHandler := NewGreetHandler(helloGRPCClient)
// Register HTTP endpoint for Hello service
app.GET("/hello", greetHandler.Hello)
// Run the application
app.Run()
}
For detailed instruction on setting up a gRPC server with GoFr see the gRPC Client Documentation For more examples refer gRPC Examples
storeAvailable since:
gofr-cliv0.8.1
The gofr store command is a code generator that creates type-safe data access layers from YAML configuration files. It eliminates boilerplate code while maintaining GoFr's best practices for observability and context management.
*gofr.Context for built-in observability.stores/all.go.Create a new store directory and a store.yaml configuration template. The -name flag is required.
gofr store init -name=<store-name>
Example:
gofr store init -name=user
This creates the following structure:
stores/store.yaml — Configuration file template (shared across all stores).stores/all.go — Store registry factory (auto-generated, DO NOT EDIT).stores/user/interface.go — Initial interface stub (DO NOT EDIT — regenerated by generate).stores/user/user.go — Initial implementation stub (editable — add your SQL logic here).Generate or update Go code from your store configuration file.
gofr store generate
💡 Note: By default, this command looks for the configuration at
stores/store.yaml. To use a different path, use the-configflag:bashgofr store generate -config=path/to/store.yaml
Step 1: Initialize Configuration
gofr store init -name=user
Step 2: Define Your Store in stores/store.yaml
version: "1.0"
stores:
- name: "user"
package: "user"
output_dir: "stores/user"
interface: "UserStore"
implementation: "userStore"
queries:
- name: "GetUserByID"
sql: "SELECT id, name, email FROM users WHERE id = ?"
type: "select"
model: "User"
returns: "single"
params:
- name: "id"
type: "int64"
description: "Retrieves a user by their ID"
- name: "GetAllUsers"
sql: "SELECT id, name, email FROM users"
type: "select"
model: "User"
returns: "multiple"
description: "Retrieves all users"
models:
- name: "User"
fields:
- name: "ID"
type: "int64"
tag: 'db:"id" json:"id"'
- name: "Name"
type: "string"
tag: 'db:"name" json:"name"'
- name: "Email"
type: "string"
tag: 'db:"email" json:"email"'
Step 3: Generate Store Code
gofr store generate
This generates:
stores/
├── store.yaml # Central Configuration
├── all.go # Store registry factory (auto-generated)
└── user/
├── interface.go # UserStore interface definition
├── userStore.go # userStore implementation boilerplate
└── user.go # User model struct
Step 4: Use in Your Application
package main
import (
"gofr.dev/pkg/gofr"
"your-project/stores/user"
)
func main() {
app := gofr.New()
userStore := user.NewUserStore()
app.GET("/users/{id}", func(ctx *gofr.Context) (interface{}, error) {
id, _ := strconv.ParseInt(ctx.PathParam("id"), 10, 64)
return userStore.GetUserByID(ctx, id)
})
app.GET("/users", func(ctx *gofr.Context) (interface{}, error) {
return userStore.GetAllUsers(ctx)
})
app.Run()
}
You can define all stores in a single YAML file. Each store gets its own output directory and all are registered into the same stores/all.go registry.
version: "1.0"
stores:
- name: "user"
package: "user"
output_dir: "stores/user"
interface: "UserStore"
implementation: "userStore"
queries: [...]
- name: "product"
package: "product"
output_dir: "stores/product"
interface: "ProductStore"
implementation: "productStore"
queries: [...]
models:
- name: "User"
fields: [...]
- name: "Product"
fields: [...]
Generated structure:
stores/
├── all.go
├── user/
│ ├── interface.go
│ ├── userStore.go
│ └── user.go
└── product/
├── interface.go
├── productStore.go
└── product.go
Using the registry with multiple stores:
import (
"your-project/stores"
"your-project/stores/user"
"your-project/stores/product"
)
// stores.GetStore returns a factory-created instance
userStore := stores.GetStore("user").(user.UserStore)
productStore := stores.GetStore("product").(product.ProductStore)
💡 Note:
stores.All()returns amap[string]func() any— a map of factory functions, not active instances.stores.GetStore(name)calls the factory for you and returns the instance.
| Field | Description | Required |
|---|---|---|
name | Store identifier used in the registry key. | Yes |
package | Go package name for generated code. | Yes |
output_dir | Directory path where files will be generated. | Optional (defaults to stores/<name>) |
interface | Interface name — recommended: <Name>Store (e.g., UserStore). | Optional (defaults to <Name>Store) |
implementation | Private struct name for the implementation (e.g., userStore). | Optional (defaults to <name>Store) |
queries | List of database queries. | Optional |
⚠️ Naming Convention: The registry (
stores/all.go) uses a hardcoded<Name>Storepattern when generating constructor calls (e.g.,NewUserStore()). Always name your interface as<Name>Storeto avoid compilation errors.
select — SELECT queries.insert — INSERT queries.update — UPDATE queries.delete — DELETE queries.single — Returns (Model, error).multiple — Returns ([]Model, error).count — Returns (int64, error).custom — Returns (any, error).params:
- name: "id"
type: "int64"
- name: "email"
type: "string"
Supported parameter types include all Go primitive types, time.Time, and pointer types (e.g., *int64).
models:
- name: "User"
fields:
- name: "ID"
type: "int64"
tag: 'db:"id" json:"id"'
- name: "Name"
type: "string"
tag: 'db:"name" json:"name"'
- name: "CreatedAt"
type: "time.Time"
tag: 'db:"created_at" json:"created_at"'
This generates:
type User struct {
ID int64 `db:"id" json:"id"`
Name string `db:"name" json:"name"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
func (User) TableName() string {
return "user"
}
If you already have models defined elsewhere:
models:
- name: "User"
path: "../models/user.go"
package: "your-project/models"
interface.go)// Code generated by gofr.dev/cli/gofr. DO NOT EDIT.
package user
import "gofr.dev/pkg/gofr"
type UserStore interface {
GetUserByID(ctx *gofr.Context, id int64) (User, error)
GetAllUsers(ctx *gofr.Context) ([]User, error)
}
userStore.go)// Code generated by gofr.dev/cli/gofr. DO NOT EDIT.
package user
type userStore struct{}
func NewUserStore() UserStore {
return &userStore{}
}
func (s *userStore) GetUserByID(ctx *gofr.Context, id int64) (User, error) {
// TODO: Implement using ctx.SQL()
var result User
// err := ctx.SQL().QueryRowContext(ctx, sql, id).Scan(&result.ID, ...)
return result, nil
}
func (s *userStore) GetAllUsers(ctx *gofr.Context) ([]User, error) {
// TODO: Implement using ctx.SQL()
return []User{}, nil
}
// TODO: Implement sections with actual SQL execution using ctx.SQL() methods.<Name>Store Interface Names: The registry assumes this convention. E.g., interface: "UserStore" results in the constructor NewUserStore() and type assertion .(user.UserStore).store.yaml to keep your data access layer centrally configured.interface.go and all.go are marked DO NOT EDIT and are overwritten on every gofr store generate. The implementation stub (<name>.go) created by gofr store init is editable — this is where you add your SQL logic. The userStore.go generated by gofr store generate is also editable boilerplate.store.yaml. Re-run gofr store generate after any configuration change to sync the generated interfaces.For a complete working example of the store generator, see the store example in the gofr-cli repository.
For detailed configuration options and advanced usage, refer to the Store Generator README.