我正在尝试将 go 模块与一些尚未推送到 github 的本地代码一起使用(golang 版本为 1.12.7)
到目前为止,我有 3 个模块都在同一个父根目录下(兄弟文件夹)。maps
并且go-database-util
已经被推送,但是该模块应该使用我本地的任何内容(而且我还没有为 git repo 创建go-log-util
),所以我认为这不相关。
/maps
go.mod
go.sum
main.go
/api
...more files (just a regular package, not a module)
/go-database-util
db.go
go.mod
go.sum
/go-log-util
log.go
go.mod
go.sum
go-database-util
和都是go-log-util
库,不提供主包。有趣的是,go-database-util
在导入 /maps/main.go 时工作正常,但在尝试导入时并非如此go-log-util
。这是我尝试时得到的go build
maps
:
build github.com/X/maps: cannot load github/X/go-log-util: cannot find module providing package github/X/go-log-util
这里发生了什么?我一直在努力从go dep
to go 模块迁移,但到目前为止还没有运气。
相关代码如下。
非常感谢!:)
/maps/main.go
package main
import (
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
log "github/X/go-log-util"
dbUtil "github.com/X/go-database-util"
"github.com/X/maps/api"
"github.com/gorilla/mux"
"github.com/jinzhu/gorm"
"github.com/namsral/flag"
"github.com/sirupsen/logrus"
"github.com/urfave/negroni"
)
type configuration struct {
Addr string
LogLevel string
DBSettings dbUtil.Settings
}
var (
config configuration
db *gorm.DB
)
func main() {
loadConfig()
flag.Parse()
logrus.Infof("Using config: %#v", config)
var err error
db, err = dbUtil.Setup(config.DBSettings)
if err != nil {
logrus.Fatal(err)
}
n := negroni.New()
n.Use(negroni.HandlerFunc(log.LoggingMiddleware))
router := mux.NewRouter()
userRoutes := mux.NewRouter()
userRoutes.HandleFunc("/api/maps/info", api.HandleRead).Methods("GET")
n.UseHandler(router)
srv := &http.Server{
Handler: n,
Addr: config.Addr,
}
setupCleanupHandler()
logrus.Fatal(srv.ListenAndServe())
}
func loadConfig() {
flag.StringVar(&config.Addr, "addr", "localhost:8080", "HTTP service address")
flag.StringVar(&config.LogLevel, "log-level", "debug",
"Application logging level (debug, info, warning, error, fatal, panic)")
var dbPassword string
var connMaxLifetime int
flag.StringVar(&config.DBSettings.Host, "db-host", "", "DB host")
flag.StringVar(&config.DBSettings.User, "maps-db-username", "", "DB user")
flag.StringVar(&config.DBSettings.DBName, "maps-db-name", "X", "DB name")
flag.StringVar(&dbPassword, "maps-db-password", "", "DB password")
flag.IntVar(&config.DBSettings.MaxIdleConns, "db-max-idle-conns", 10, "DB max idle connections")
flag.IntVar(&config.DBSettings.MaxOpenConns, "db-max-open-conns", 100, "DB max open connections")
flag.BoolVar(&config.DBSettings.LogEnabled, "db-enable-log", false, "Enable detailed gorm log")
flag.IntVar(&connMaxLifetime, "db-max-lifetime-conns", 5, "DB max connection lifetime (minutes)")
config.DBSettings.Password = &dbPassword
config.DBSettings.ConnMaxLifetime = time.Duration(connMaxLifetime) * time.Minute
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "OK SO")
}
func setupCleanupHandler() {
sigs := make(chan os.Signal, 2)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigs
logrus.Info("Server shutdown, cleaning up resources")
db.Close()
os.Exit(1)
}()
}
/maps/go.mod
module github.com/X/maps
go 1.12
require (
github.com/X/go-database-util v0.0.0
github.com/X/go-log-util v0.0.0
github.com/gorilla/mux v1.6.2
github.com/jinzhu/gorm v1.9.10
github.com/namsral/flag v1.7.4-pre
github.com/sirupsen/logrus v1.4.2
github.com/urfave/negroni v1.0.0
)
replace github.com/X/go-log-util => ../go-log-util
replace github.com/X/go-database-util => ../go-database-util
/go-database-util/db.mod
// Package db provides utility functions to perform database related tasks.
// While most of the code is generic, it assumes to be working using a postgres driver.
package db
import (
"fmt"
"time"
"github.com/jinzhu/gorm"
// required in order to load postgres driver.
_ "github.com/jinzhu/gorm/dialects/postgres"
"github.com/sirupsen/logrus"
)
// Settings store a database main configuration options.
type Settings struct {
Host string
User string
DBName string
Password *string
MaxIdleConns int
MaxOpenConns int
ConnMaxLifetime time.Duration
LogEnabled bool
}
// Setup configures the settings for database connections.
func Setup(s Settings) (*gorm.DB, error) {
connURL := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable password=%s",
s.Host, s.User, s.DBName, *s.Password)
db, err := gorm.Open("postgres", connURL)
if err != nil {
return nil, err
}
db.DB().SetMaxIdleConns(s.MaxIdleConns)
db.DB().SetMaxOpenConns(s.MaxOpenConns)
// broken connections may not be detected; would need a dedicate goroutine
// setting this to just a few seconds / minutes will solve a lot of issues
// see https://github.com/go-sql-driver/mysql/issues/529
db.DB().SetConnMaxLifetime(s.ConnMaxLifetime)
db.LogMode(s.LogEnabled)
logger := logrus.New()
db.SetLogger(logger)
return db, nil
}
go-database-util/go.mod
module github.com/X/go-database-util
go 1.12
require (
github.com/jinzhu/gorm v1.9.10
github.com/sirupsen/logrus v1.4.2
)
go-log-util/log.go
package log
import (
"context"
"net/http"
"os"
"github.com/sirupsen/logrus"
)
const (
// RequestIDHeader is the header name for the request id.
RequestIDHeader = "X-Request-Id"
// UserIDKey is the key for the user id inside the logger fields.
UserIDKey = "UserID"
)
// RequestContext returns a new context with the argument context fields
// and a request id.
func RequestContext(ctx context.Context, req *http.Request) context.Context {
requestID := req.Header.Get(RequestIDHeader)
reqContext := context.WithValue(ctx, RequestIDHeader, requestID)
return reqContext
}
// L returns logrus entry with context information.
func L(ctx context.Context) *logrus.Entry {
logger := logrus.New()
Configure(logger)
l := logrus.Fields{
RequestIDHeader: RequestID(ctx),
}
if id := UserID(ctx); id != 0 {
l[UserIDKey] = id
}
return logger.WithFields(l)
}
// RequestID returns the request id from the context.
func RequestID(ctx context.Context) string {
if id, ok := ctx.Value(RequestIDHeader).(string); ok {
return id
}
return ""
}
// UserID returns the user id from the context.
func UserID(ctx context.Context) uint64 {
if id, ok := ctx.Value(UserIDKey).(uint64); ok {
return id
}
return 0
}
// Setup initializes and sets configuration options for the logger.
func Setup(logLevel string, logger *logrus.Logger) {
logger.Formatter = &logrus.TextFormatter{
FullTimestamp: true,
}
logger.Out = os.Stdout
level, _ := logrus.ParseLevel(logLevel)
logger.Level = level
}
// Configure initializes and set configuration options for the logger.
func Configure(logger *logrus.Logger) {
logger.Formatter = &logrus.TextFormatter{
FullTimestamp: true,
}
logger.Out = os.Stdout
logger.Level = logrus.StandardLogger().Level
}
// LoggingMiddleware creates a middleware that logs useful information from an
// *http.Request
func LoggingMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
ctx := RequestContext(r.Context(), r)
logFields := logrus.Fields{
"remoteAddr": r.RemoteAddr,
"method": r.Method,
"url": r.URL,
"x-forwarded-for": r.Header.Get("X-Forwarded-For"),
}
L(ctx).WithFields(logFields).Info("Incoming request")
next(w, r.WithContext(ctx))
}
go-log-util/go.mod
module github.com/X/go-log-util
go 1.12
require github.com/sirupsen/logrus v1.4.2