Related issue (didn't help me at all): https://github.com/golang/go/issues/16208
I'm lost. Can someone please help me? No clue how to fix this and nothing I've found online helps. As far as I can tell, there's nothing wrong with my code...
go version
)?1.8.3
go env
)?GOARCH="amd64"
GOBIN="/Users/lcamara/Projects/Go/src/app/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/lcamara/Projects/Go/src/app"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.8.3/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.8.3/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/5g/g6v5m26j7_b_bgvv__q32frh0000gp/T/go-build778985185=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
I did go run main.go
, as I always do.
This is main.go
:
package main
import (
"database/sql"
"log"
"fmt"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"microservices/www_api/middleware"
"microservices/www_api/controllers"
"microservices/www_api/services"
"domain"
"repositories"
"infrastructure/env"
)
func main() {
// Create a new default router with no middleware.
router := gin.New()
// Load environment variables.
e := env.New()
if err := e.Load("../../../.env.json"); err != nil {
log.Fatal(err.Error())
}
// Start MySQL
db, err := sql.Open(
"mysql",
fmt.Sprintf(
"%s:%s@tcp(%s:%s)/%s",
e.Databases.MySQL.Username,
e.Databases.MySQL.Password,
e.Databases.MySQL.Host,
e.Databases.MySQL.Port,
e.Databases.MySQL.Database,
),
)
if err != nil {
log.Fatal(err.Error())
}
defer db.Close()
// Make sure connection is available.
err = db.Ping()
if err != nil {
log.Fatal(err.Error())
}
// Set the system clock.
domain.SetSystemClock(&domain.NormalClock{})
// Initialize repositories by injecting DB.
r := repositories.New(db)
// Initialize services by injecting repos.
s := services.New(r) // =======================> THIS IS WHERE THE ERROR HAPPENS
// Add global middleware.
middleware.Load(router)
// Set api v1 group.
apiV1RouterGroup := router.Group("/api/v1")
// Load routes.
controllers.Load(apiV1RouterGroup, s)
// Listen for requests.
router.Run(fmt.Sprintf(":%s", e.Microservices.WWWAPI.Port))
}
If we go to the code of the line where the error happens (services.go
):
package services
import "repositories"
type Service struct {
UserService *UserService
TokenService *TokenService
}
func New(repos *repositories.Repository) *Service {
s := new(Service)
s.UserService = NewUserService(repos)
s.TokenService = NewTokenService(repos)
return s
}
As you can see there is nothing exciting going on there...
I expected the server to start listening on port 8080 and to run as normal.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x1515edd]
goroutine 1 [running]:
main.main()
/Users/lcamara/Projects/Go/src/app/src/microservices/www_api/main.go:59 +0x39d
The traceback might be giving you the wrong file and line number due to inlining. There are some fixes for that in Go 1.9 (see https://tip.golang.org/doc/go1.9#runtime) — try go1.9beta2 and see if that clarifies things.
I was able to stop this error by changing this:
package services
import "repositories"
type Service struct {
UserService *UserService
TokenService *TokenService
}
func New(repos *repositories.Repository) *Service {
s := new(Service)
s.UserService = NewUserService(repos)
s.TokenService = NewTokenService(repos)
return s
}
To this:
package service
import (
"repository"
)
type Bus struct {
UserService *UserService
TokenService *TokenService
}
func New(repositoryBus *repository.Bus) *Bus {
return &Bus{
UserService: NewUserService(repositoryBus),
TokenService: NewTokenService(repositoryBus),
}
}
Basically, instead of creating a new instance of that struct and setting the properties, I just return a pointer to the struct directly. Did that in all of the packages where I had similar dependency injection logic (repositories, controllers, etc.), and for whatever reason the error has now gone away.
Also changed the redundant services.Service
to now a more readable (at least to me) service.Bus
, in case you were confused about the names.
@lansana Are you able to reproduce this on go1.9? or are you able to provide an example that can reproduce this?
@kardianos I haven't yet tested it on go 1.9 but as stated in previous post I was able
to resolve this by modifying my code slightly.
On Thu, Sep 7, 2017 at 4:48 PM Daniel Theophanes notifications@github.com
wrote:
@lansana https://github.com/lansana Are you able to reproduce this on
go1.9? or are you able to provide an example that can reproduce this?—
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/golang/go/issues/20942#issuecomment-327923080, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AOHoHskMhMfEUtNqgsty1PaByDHbKMZpks5sgFacgaJpZM4OQztc
.
Should we close this issue then? If this was resolved by changing your own code and the first line in the panic references your main file, then I would be inclined to say it may have been a programmer error.
@kardianos It can be closed, sure, but I'm not sure it would be a programmer error because there's nothing syntactically wrong with the following bit of code:
func New(repos *repositories.Repository) *Service {
s := new(Service)
s.UserService = NewUserService(repos)
s.TokenService = NewTokenService(repos)
return s
}
...but for whatever reason, that code is what gave the error. And when changed to this:
func New(repos *repositories.Repository) *Service {
return &Service{
UserService: NewUserService(repos),
TokenService: NewTokenService(repos),
}
}
...the error went away.
I don't see why the two approaches are any different, because they both achieve the same thing which is creating and returning a pointer to a Service
struct.
But go ahead and close since I solved this a while ago. :)
Thanks!
Hi @lansana
I have a similar problem in my case. Do you already know how these two approaches differ?
@lkobylski This is a closed issue and isn't tracked.
Please open a new issue, detail the version of Go you are using and any sql drivers and their version as well. If this is related to database/sql, please include my handle @kardianos in the message.
It doesn't really give me much confidence that you can just close the error, when there is in fact, an error. How is brushing it under the rug any help at all? This issue pops up as the very first result in Google. Obviously, it's still happening, even with go1.9.3.
This is a closed issue and isn't tracked.
Please open a new issue, detail the version of Go you are using and any sql drivers and their version as well. If this is related to database/sql, please include my handle @kardianos in the message.
Most helpful comment
It doesn't really give me much confidence that you can just close the error, when there is in fact, an error. How is brushing it under the rug any help at all? This issue pops up as the very first result in Google. Obviously, it's still happening, even with go1.9.3.