Having trouble splitting go code in multiple files - go

I have two files main.go and group.go... it looks something like this
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
// Creates a gin router with default middlewares:
// logger and recovery (crash-free) middlewares
router := gin.Default()
v1 := router.Group("/v1")
{
v1.GET("/", func (c *gin.Context) {
c.JSON(http.StatusOK, "{'sup': 'dup'}")
})
groups := v1.Group("/groups")
{
groups.GET("/", groupIndex)
groups.GET("/:id", groupShow)
groups.POST("/", groupCreate)
groups.PUT("/:id", groupUpdate)
groups.DELETE("/:id", groupDelete)
}
}
// Listen and server on 0.0.0.0:8080
router.Run(":3000")
}
So the methods groupIndex, groupCreate, groupUpdate, etc are located in another file under routes/group.go
package main
import (
"strings"
"github.com/gin-gonic/gin"
)
func groupIndex(c *gin.Context) {
var group struct {
Name string
Description string
}
group.Name = "Famzz"
group.Description = "Jamzzz"
c.JSON(http.StatusOK, group)
}
func groupShow(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupShow': 'someContent'}")
}
func groupCreate(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupShow': 'someContent'}")
}
func groupUpdate(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupUpdate': 'someContent'}")
}
func groupDelete(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupDelete': 'someContent'}")
}
But when I try to compile I get the following error
stuff/main.go:21: undefined: groupIndex
stuff/main.go:23: undefined: groupShow
stuff/main.go:24: undefined: groupCreate
stuff/main.go:25: undefined: groupUpdate
stuff/main.go:26: undefined: groupDelete
I'm super new to go, but I thought if you put files in the same package, then they'll have access to each other. What am I doing wrong here?

There are two ways to fix this:
Move group.go to the same directory as main.go.
Import group.go as a package. Change the package declaration on group.go to:
package routes // or the name of your choice
Export the functions by starting them with a capital letter:
func GroupIndex(c *gin.Context) {
Import the package from main:
import "path/to/routes"
...
groups.GET("/", routes.GroupIndex)
The document How To Write Go Code explains this and more.

Related

How to set Routes Group in Go Fiber V2 from separated file?

I want to make seperate files for each sub main routes. I am using go 1.17
main.go
package main
import (
"rolling_glory_go/routes"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
err := c.SendString("Hello golang!")
return err
})
routes.R_login(app.Group("/login"))
routes.R_users(app.Group("/users"))
app.Listen(":3000")
}
I want to import routes from r_login.go and r_users.go so i could manage many routes from different files and not put many routes from single file in main.go. I got an error like this.
.\main.go:17:26: cannot use app.Group("/login") (type fiber.Router) as type *fiber.Group in argument to routes.R_login: need type assertion
.\main.go:18:26: cannot use app.Group("/users") (type fiber.Router) as type *fiber.Group in argument to routes.R_users: need type assertion
My Structure Folder
r_login.go
package routes
import "github.com/gofiber/fiber/v2"
func R_login(router *fiber.Group) {
router.Get("/", func(c *fiber.Ctx) error {
return c.SendString("respond with a resource")
})
}
r_users.go
package routes
import "github.com/gofiber/fiber/v2"
func R_users(router *fiber.Group) {
router.Get("/", func(c *fiber.Ctx) error {
return c.SendString("respond with a resource")
})
}
How to fix this ?
As you have app.Group("/login") which of type fiber.Router
, just modify R_login to have it accept this type.
package routes
import "github.com/gofiber/fiber/v2"
func R_login(router fiber.Router) {
router.Get("/", func(c *fiber.Ctx) error {
return c.SendString("respond with a resource")
})
}

invalid receiver error when using Gin Gonic framework in Go

I am trying to use an external (non anonymous) function in the routing of my Gin based web server as shown below:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/hi/", Hi)
router.Run(":8080")
}
func (c *gin.Context) Hi() {
c.String(http.StatusOK, "Hello")
}
But I get 2 errors:
./main.go:13:23: undefined: Hi
./main.go:18:6: cannot define new methods on non-local type gin.Context
I am wondering how I can use anonymous functions in my endpoint handlers with gin gonic? All the documentation I've found so far uses anonymous functions.
Thanks!
You can only define a new method for a type in the same package declaring that type. That is, you cannot add a new method to gin.Context.
You should do:
func Hi(c *gin.Context) {
...
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
router.GET("/hi", hi)
var n Node
router.GET("/hello", n.hello)
router.GET("/extra", func(ctx *gin.Context) {
n.extra(ctx, "surprise~")
})
router.Run(":8080")
}
func hi(c *gin.Context) {
c.String(200, "hi")
}
type Node struct{}
func (n Node) hello(c *gin.Context) {
c.String(200, "world")
}
func (n Node) extra(c *gin.Context, data interface{}) {
c.String(200, "%v", data)
}

How to group routes in gin?

I want to group my routes in different files, so the main file won't be very messy.
I want something like this in their own files:
v1 := router.Group("/v1")
{
v1.Group("users", usersRoutes)
v1.Group("pictures", picturesRoutes)
v1.Group("friends", friendsRoutes)
}
So each one of the *Routes would look something like this:
users := v1.Group("/users")
{
users.GET("/", getUsers)
users.POST("/", createUser)
}
Is this possible? Right now my code looks like this:
package app
import (
"net/http"
"github.com/gin-gonic/gin"
)
func getUrls() {
v1 := router.Group("/v1")
{
ping := v1.Group("/ping")
{
ping.GET("/", pongFunction)
}
users := v1.Group("/users")
{
users.GET("/", getUsersFunction)
}
}
}
But this is going to increase its size a lot.
You would need to store router variable in your struct or global variable. Then individual go files will add handlers to that variable. Here is an example:
routes.go
package app
import (
"github.com/gin-gonic/gin"
)
type routes struct {
router *gin.Engine
}
func NewRoutes() routes {
r := routes{
router: gin.Default(),
}
v1 := r.router.Group("/v1")
r.addPing(v1)
r.addUsers(v1)
return r
}
func (r routes) Run(addr ...string) error {
return r.router.Run()
}
ping.go
package app
import "github.com/gin-gonic/gin"
func (r routes) addPing(rg *gin.RouterGroup) {
ping := rg.Group("/ping")
ping.GET("/", pongFunction)
}
func pongFunction(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
}
users.go
package app
import "github.com/gin-gonic/gin"
func (r routes) addUsers(rg *gin.RouterGroup) {
users := rg.Group("/users")
users.GET("/", getUsersFunction)
}
func getUsersFunction(c *gin.Context) {
c.JSON(200, gin.H{
"users": "...",
})
}

How to get matched route in context in Gin?

I have this code :
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.New()
r.GET("/user/:id", func(c *gin.Context) {
// How can I get the litteral string "/user/:id" here ?
c.JSON(http.StatusOK, gin.H{"message": "received request"})
})
}
Is there any way that I can retrieve inside the handler the litteral string /user/:id? If I use c.Request.Path it will give me the full output of the path like /user/10.
According to the documentation you can use FullPath().
router.GET("/user/:id", func(c *gin.Context) {
c.FullPath() == "/user/:id" // true
})

golang gin: router like django?

Can gin describe route like django?
In all examples, the routers are in one place, never found about attachment.
I would like to describe the routes in the package, and in the main file is simply to write something like.
example:
r := gin.New()
r.Include("/main", here_imported_route.Route)
here_imported_route.go
package here_imported_route
Router := gin.New()
Router.Use(midl())
Router.Get("/test", hello)
and then on "/main/test" we get "hello".
in main route like here
package main
import (
"path_to_pkg/pkg"
"github.com/gin-gonic/gin"
)
var r *gin.Engine
func init() {
r = gin.New()
pkg.Concon(r.Group("/pkg"))
}
func main() {
r.Run(":8080")
}
in imported package create concatenation func
pkg.go
package pkg
import "github.com/gin-gonic/gin"
func Concon(g *gin.RouterGroup) {
g.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
}
open 127.0.0.1:8080/pkg/ping and get "pong"
If I understand your question correctly, I think you can accomplish this with route grouping. So you would have something like this:
r := gin.New()
main := r.Group("/main")
{
main.GET("/test", hello)
}
See more details here.

Resources