【问题标题】:Multiple go files in Docker buildDocker 构建中的多个 go 文件
【发布时间】: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 buildCMD 使用go run?为什么不运行 go-build 二进制文件?然后使用多阶段 docker build 将此 exe 复制到“scratch”映像 - 以使最终映像尽可能小。

标签: linux docker go


【解决方案1】:

问题在于您的 Dockerfile,特别是 CMD(最后一行)。

我对此进行了测试,它确实有效..

# ~ Dockerfile ~
# ...
# CMD ["go", "run", "/app/server.go"] # <- Remove this
CMD ["go", "run", "."] # <- Add this

编辑:发生这种情况的原因是因为您专门运行server.go。意思是,handlers.go 没有与server.go 一起编译,指定句点告诉go 构建/运行当前目录中的所有文件。我不确定你是如何在本地使用 go run server.go 的(我无法让它工作,我不得不使用 go run .

【讨论】:

  • 是的,我错过了这个。这似乎是正确的答案。
  • 你打赌!干杯!! @pigfox
猜你喜欢
  • 2012-04-13
  • 2018-05-07
  • 2018-11-04
  • 2020-01-08
  • 1970-01-01
  • 2019-10-08
  • 2020-04-07
  • 2016-12-12
  • 2023-04-05
相关资源
最近更新 更多