Go cannot call NewRouter() function [duplicate] - go

This question already has answers here:
go build works fine but go run fails
(3 answers)
Closed 7 years ago.
I'm new to Go, but I'm trying to create a RESTful API using Gorilla Mux to create my router based on this article http://thenewstack.io/make-a-restful-json-api-go/
I have a Router file with the below code in it.
package main
import (
"net/http"
"github.com/gorilla/mux"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
return router
}
var routes = Routes{
Route{
"Index",
"GET",
"/",
Index,
},
}
And in my Main.go I have this:
package main
import (
"log"
"net/http"
)
func main() {
router := NewRouter()
log.Fatal(http.ListenAndServe(":8080", router))
}
From what I know about Go and how to call a method in one file from another this should work. But when I run: go build Main.go I get this error in my console:
go run Main.go
# command-line-arguments
./Main.go:10: undefined: NewRouter
I've run go get in my src folder which has all my files in it to get gorilla, but that didn't fix it. What am I doing wrong here?

If your main package consists of multiple .go files, you have to pass all to go run, e.g.:
go run Main.go Router.go

Related

How to access another file in GO

I'm trying to access a controller from main.go but I'm getting the following error:
./main.go:34:28: cannot refer to unexported name controllers.getUserDetails
./main.go:34:28: undefined: controllers.getUserDetails
here's a snippet of my main.go, I've removed some extra code
package main
import (
"net/http"
"os"
"log"
"github.com/urfave/negroni"
"github.com/gorilla/mux"
"github.com/joho/godotenv"
"Go-Social/controllers"
)
func main() {
router := mux.NewRouter()
UserRouter := router.PathPrefix("/api/user").Subrouter()
UserRouter.HandleFunc("", controllers.getUserDetails).Methods("GET")
env := os.Getenv("GO_ENV")
if "" == env {
env = "Development"
}
// appending middlewares
server := negroni.Classic()
// router handler with negroni
server.UseHandler(router)
// starting server
server.Run(":" + os.Getenv(env + "_PORT"))
}
my controller.go file
package controllers
import (
"net/http"
"fmt"
)
func getUserDetails(w http.ResponseWriter, r *http.Request) {
fmt.Println("here")
message := "Hello World"
w.Write([]byte(message))
}
Please Help I'm new to Go. Thanks in advance.
to use a function from another package, you need to export it (GetUserDetails)
as said here
An identifier may be exported to permit access to it from another package
func GetUserDetails(w http.ResponseWriter, r *http.Request) {
fmt.Println("here")
message := "Hello World"
w.Write([]byte(message))
}
Since the getUserDetails function is in another package it cannot be accessed. Only functions starting with capital letter can be accessed. That's how encapsulation works in Go.
func GetUserDetails(w http.ResponseWriter, r *http.Request) {
fmt.Println("here")
message := "Hello World"
w.Write([]byte(message))
}
So in your main:
UserRouter.HandleFunc("", controllers.GetUserDetails).Methods("GET")
Language like Java, enCAPSulation in class-based OOP is achieved through private and public class variables / methods.
In Go, encapsulation is achieved on a package level.
In other words, in Go, starting with capital letter for any package object (type, variable or function) will allow you to access it from another package.

Golang routing in different controllers

I am new to Golang and I am trying to learn how to do efficient routing. For instance I have a controller folder/directory and inside that controller I want to have different Func/methods with their own unique routes but I do not know how to do that. I have downloaded the github.com/gorilla/mux package and my application looks like this
The main section of my application looks like this and it is working perfectly: tim.go
package main
import(
"net/http"
"fmt"
"github.com/gorilla/mux"
)
func HomeHandler(writer http.ResponseWriter, req *http.Request) {
writer.WriteHeader(200)
fmt.Fprintf(writer, "Home!!!\n")
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/home", HomeHandler).Name("bob")
http.Handle("/",r)
http.ListenAndServe(":8000", nil)
}
The issue is how can I get the func/methods inside my Controller file(s) to also display on the browser. My sample.go file does not show in the browser when I go to that URL
package Controllers
import(
"net/http"
"fmt"
"github.com/gorilla/mux"
)
func HomeHandler(writer http.ResponseWriter, req *http.Request) {
writer.WriteHeader(200)
fmt.Fprintf(writer, "New Home")
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/new", HomeHandler).Name("bob")
http.Handle("/",r)
http.ListenAndServe(":8000/new", nil)
}
When I go into my browser and type localhost:8000/new it says file not found. Any suggestions would be great
I suppose you run the tim.go file to start the server.
If so, the problem is you don't have the route you're calling /new, you should have an answer with /home.
To do it, you should move your HomeHandler function to Controllers package and then import this package in your main ad instantiate the routes you need.
Hope this helps.

Gorilla Mux routes not resolving

So, I'm working on a simple RESTful API using Go and Gorilla Mux. I'm having issues with with my second route not working, it's returning a 404 error. I'm not sure what the problem is as I'm new to Go and Gorilla. I'm sure it's something really simple, but I can't seem to find it. I think it might be a problem with the fact that I'm using different custom packages.
This question is similar, Routes returning 404 for mux gorilla, but the accepted solution didn't fix my problem
Here's what my code looks like:
Router.go:
package router
import (
"github.com/gorilla/mux"
"net/http"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
return router
}
var routes = Routes{
Route{
"CandidateList",
"GET",
"/candidate",
CandidateList,
},
Route{
"Index",
"GET",
"/",
Index,
},
}
Handlers.go
package router
import (
"fmt"
"net/http"
)
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome!")
}
func CandidateList(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "CandidateList!")
}
Main.go
package main
import (
"./router"
"log"
"net/http"
)
func main() {
rout := router.NewRouter()
log.Fatal(http.ListenAndServe(":8080", rout))
}
Going to just localhost:8080 returns Welcome! but going to localhost:8080/candidate returns a 404 Page Not Found error. I appreciate any input and help! Thanks!
This is an updated version of my Router.go file, there is still the same issue happening.
Router.go
package router
import (
"github.com/gorilla/mux"
"net/http"
)
type Route struct {
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Handler(route.HandlerFunc).GetError()
}
return router
}
var routes = Routes{
Route{
"GET",
"/candidate",
CandidateList,
},
Route{
"GET",
"/",
Index,
},
}
It appears that my project was holding onto old versions of the Router.go and Handlers.go files in the main src directory. By removing these duplicate files and re-running Main.go with go run Main.go I was able to get the route to be recognized.

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.

Running multi-file go program

So I'm pretty new to go and I'm trying to follow this tutorial -
http://thenewstack.io/make-a-restful-json-api-go/
Right now, this is my file structure -
EdData/
dataEntry/
populateDb.go
main.go
handlers.go
routes.go
When I run go run main.go, I get this error ./main.go:11: undefined: NewRouter
This is what my main.go looks like -
package main
import (
"net/http"
"log"
)
func main() {
router := NewRouter()
log.Fatal(http.ListenAndServe(":8080", router))
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
This is what my routes.go looks like
package main
import (
"net/http"
"github.com/gorilla/mux"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes[]Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
return router
}
var routes = Routes{
Route {
"Index",
"GET",
"/",
Index,
},
}
and this is what my handlers.go looks like
package main
import (
"fmt"
"net/http"
)
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "WELCOME!")
}
When I try and build routes.go, I get that Index is undefined, and when I try and build handlers.go, I get
# command-line-arguments
runtime.main: undefined: main.main
How do I get this to run? Also, where do I execute the go run command? Do I need to manually build all the dependent files?
From the go run help:
usage: run [build flags] [-exec xprog] gofiles... [arguments...]
Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix.
Only the files passed to go run will be included in the compilation (excluding imported packages). Therefore, you should specify all of your Go source files when using go run:
go run *.go
# or
go run main.go handlers.go routes.go

Resources