添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • missing Location in call to Date
  • panic: time: missing Location in call to Time.In
    goroutine 1 [running]:
    time.Time.In(...)
            /usr/local/go/src/time/time.go:1146
    main.main()
            /app/main.go:16 +0x1c5
    

    Does your code look somewhat like this?

    location, _ := time.LoadLocation("Europe/Amsterdam")
    name, offset := time.Now().In(location).Zone()
    log.Println("name: "+name, "offset: "+strconv.Itoa(offset))
    

    Are you using Alpine or a similar distribution in your Docker container?

    Are you using a multistep Dockerfile build process?

    Alpine does not contain timezone data inside the distribution. This means, the time.LoadLocation returns a nil for loading the location, leading to the panic at time.Now().In .

    The Solution

    At first, I suggest changing the code in a way that the error is getting caught.

    location, err := time.LoadLocation("Europe/Amsterdam")
    if err != nil {
        log.Fatal(err)
    

    Next, there are at least two solutions. Either add the timezone info into the distribution or use a base image that has timezone info.

    1. Add timezone info

    The solution is to add the timezone info in your Docker build step. But let’s clarify first why this helps.

    The Go runtime checks a couple of locations for timezone information. You can read more about the exact behaviour in the Golang LoadLocation documentation Essentially, there are 4 locations that are checked in order:

  • the directory or uncompressed zip file named by the ZONEINFO environment variable
  • on a Unix system, the system standard installation location
  • $GOROOT/lib/time/zoneinfo.zip
  • the time/tzdata package, if it was imported
  • We can see that the Go distribution contains timezone info, we can copy that and reference it via an environment variable.

    The following code assumes that the first step in your Docker file is called builder . Please change the base step name accordingly.

    Add these lines to your Dockerfile:

    # Copy timezone from Golang base image
    COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /
    # Specify timezone info location for Go application
    ENV ZONEINFO=/zoneinfo.zip
    

    Your Dockerfile might look like this in the end:

    # Build stage
    FROM golang:1.22 as builder
    # Install musl-dev and gcc for Alpine compatibility
    RUN apt-get update && apt-get install -y musl-dev musl-tools gcc
    # Set the Current Working Directory inside the container
    WORKDIR /app
    # Copy go.mod and go.sum files
    COPY go.mod go.sum ./
    # Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
    RUN go mod download
    # Copy the source code into the container
    COPY . .
    # Build the Go app
    RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o application .
    ## Final stage
    FROM alpine:latest as final
    ## Install necessary packages, e.g. ca-certificates, if your application needs it
    RUN apk --no-cache add ca-certificates
    WORKDIR /app
    ## Copy the pre-built binary file from the previous stage
    COPY --from=builder /app/application /app/application
    COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /
    ENV ZONEINFO=/zoneinfo.zip
    CMD ["/app/application"]
    

    2. Use different base image

    In case the timezone info does not work for you, you might want try using a different base image like Ubuntu. Keep in mind that this will result in larger final image sizes.

    Further Reading
  • Golang Zoneinfo
  • Golang LoadLocation()
  •