【发布时间】:2023-03-26 10:28:01
【问题描述】:
我正在构建一个 Dockeried 应用程序,我将 go 文件拆分为两个文件。
尝试运行时出现以下错误:
# command-line-arguments
./server.go:86:63: undefined: indexHandler
indexHandler 位于 server.go 中时工作正常,但我收到错误,它位于 handlers.go 中。
有什么建议吗?
//server.go
package main
import (
"database/sql"
"fmt"
"log"
"net"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
"github.com/jimlawless/whereami"
"github.com/rs/cors"
)
type FileSystem struct {
fs http.FileSystem
}
type dbConnection struct {
conn *sql.DB
}
var dbx dbConnection
var Config Configs
type Configs struct {
cookieName string
cookieValue string
cookieMaxAge int
cookieHTTPOnly bool
cookiePath string
domain string
port string
apiKey string
apiVersion string
apiPath string
protocol string
}
func setConfig() {
Config = Configs{}
Config.cookieName = os.Getenv("COOKIE_NAME")
Config.cookieValue = os.Getenv("COOKIE_VALUE")
age, err := strconv.Atoi(os.Getenv("COOKIE_MAX_AGE"))
if err != nil {
log.Println(whereami.WhereAmI(), err.Error())
}
Config.cookieMaxAge = age
Config.cookieHTTPOnly, err = strconv.ParseBool(os.Getenv("COOKIE_HTTP_ONLY"))
if err != nil {
log.Println(whereami.WhereAmI(), err.Error())
}
Config.cookiePath = os.Getenv("COOKIE_PATH")
Config.domain = os.Getenv("DOMAIN")
Config.port = os.Getenv("PORT")
Config.apiKey = os.Getenv("APP_KEY")
Config.apiVersion = os.Getenv("API_VERSION")
Config.apiPath = os.Getenv("API_PATH")
Config.protocol = os.Getenv("PROTOCOL")
}
func main() {
defer recoverPanic()
setConfig()
//db()
fmt.Println(Config)
target := Config.protocol + Config.domain + Config.port
corsOpts := cors.New(cors.Options{
AllowedOrigins: []string{target}, //you service is available and allowed for this base url
AllowedMethods: []string{
http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions, http.MethodHead,
},
AllowedHeaders: []string{
"*", //or you can your header key values which you are using in your application
},
})
router := mux.NewRouter()
router.HandleFunc(Config.apiPath+Config.apiVersion+"/index", indexHandler).Methods("GET")
router.PathPrefix("/").Handler(http.FileServer(http.Dir("./")))
http.ListenAndServe(Config.port, corsOpts.Handler(router))
}
/*
func indexHandler(w http.ResponseWriter, req *http.Request) {
addCookie(w, Config.cookieName, Config.cookieValue)
cookie, err := req.Cookie(Config.cookieName)
if err != nil {
log.Println(whereami.WhereAmI(), err.Error())
}
log.Println("Cookie: ", cookie)
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "hola")
}
*/
func addCookie(w http.ResponseWriter, name, value string) {
cookie := http.Cookie{
Name: Config.cookieName,
Value: Config.cookieValue,
Domain: Config.domain,
Path: Config.cookiePath,
MaxAge: Config.cookieMaxAge,
HttpOnly: Config.cookieHTTPOnly,
}
http.SetCookie(w, &cookie)
log.Println("Cookie added")
}
func (fs FileSystem) Open(path string) (http.File, error) {
f, err := fs.fs.Open(path)
if err != nil {
return nil, err
}
s, err := f.Stat()
if s.IsDir() {
index := strings.TrimSuffix(path, "/") + "/index.html"
if _, err := fs.fs.Open(index); err != nil {
return nil, err
}
}
return f, nil
}
func db() error {
db, err := sql.Open("mysql", "root:root@tcp(192.168.0.33:4200)/mysql")
if err != nil {
log.Print(err.Error())
} else {
log.Println("DB connected successfully")
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Println("Ping Error: " + err.Error())
} else {
dbx.conn = db
}
return err
}
func recoverPanic() {
if rec := recover(); rec != nil {
err := rec.(error)
log.Println(whereami.WhereAmI(), err.Error())
var l *net.TCPListener
file, err := l.File()
if err != nil {
log.Println(whereami.WhereAmI(), err.Error())
}
path := os.Args
args := []string{"-graceful"}
cmd := exec.Command(path[0], args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.ExtraFiles = []*os.File{file}
err2 := cmd.Start()
if err2 != nil {
log.Println(whereami.WhereAmI(), err2.Error())
} else {
log.Println(whereami.WhereAmI(), "Restarted...")
}
}
}
//handlers.go
package main
import (
"fmt"
"log"
"net/http"
"github.com/jimlawless/whereami"
)
func indexHandler(w http.ResponseWriter, req *http.Request) {
addCookie(w, Config.cookieName, Config.cookieValue)
cookie, err := req.Cookie(Config.cookieName)
if err != nil {
log.Println(whereami.WhereAmI(), err.Error())
}
log.Println("Cookie: ", cookie)
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "hola")
}
注释掉的行是我尝试过但失败的东西。
#Dockerfile
FROM golang:alpine AS builder
RUN mkdir /app
RUN rm -f go.mod go.sum
RUN go mod init xyz.com
RUN rm -f $GOPATH/go.mod
ADD . /app/
WORKDIR /app
COPY ./handlers.go .
COPY ./server.go .
COPY ./favicon.ico .
COPY ./assets /assets
COPY ./go.mod .
COPY ./go.sum .
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(ls -1 *.go)
# command-line-arguments
#./server.go:86:63: undefined: indexHandler
#RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
#RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(ls -1 *.go)
#RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o server.go handlers.go
#RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server.go handlers.go
#RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build *.go
EXPOSE 9000
#stat /app/*.go: no such file or directory
#CMD ["go", "run", "/app/*.go"]
CMD ["go", "run", "/app/server.go"]
【问题讨论】:
-
我希望不是分层。尝试
COPY handlers.go server.go go.mod go.sum .删除多行中使用的COPY,并按照我的要求进行操作。看看这是否有效! -
何必在你的 Dockerfile 中使用
go build而CMD使用go run?为什么不运行 go-build 二进制文件?然后使用多阶段 docker build 将此 exe 复制到“scratch”映像 - 以使最终映像尽可能小。