drwiupraq047311240
2017-04-24 15:25
浏览 65
已采纳

Golang IO读取文件无效的内存地址

I'm having some troubles trying to read a GZIP file from AWS S3. I have only a simple code and I'm getting the error panic: runtime error: invalid memory address or nil pointer dereference. But it still hard to find the problem.

The error message is saying that is the gzip.NewReader.... Why golang is reporting it? How could i solve it?

goroutine 1 [running]:
github.com/hensg/pushego/aws.GetGZIPProductsDump(0x7ffead44098f, 0xc, 0x7ffead44099f, 0x2f, 0x0, 0xc420190580, 0x0, 0x0)
        /home/henrique/go/src/github.com/hensg/pushego/aws/s3.go:47 +0x2e7
main.main()
        /home/henrique/go/src/github.com/hensg/pushego/pushego.go:28 +0x249

Main code (pushego.go)

package main

import (
    "bufio"
    "flag"
    "log"
    "os"
    "time"

    "github.com/hensg/pushego/aws"
)

func init() {
    log.SetOutput(os.Stdout)
}

func main() {
    log.Println("Starting...")

    var bucket, key string
    var timeout time.Duration

    flag.StringVar(&bucket, "b", "", "Bucket name")
    flag.StringVar(&key, "k", "", "Object key name")
    flag.DurationVar(&timeout, "d", 0, "Download timeout")
    flag.Parse()

    gzipReader, err := aws.GetGZIPDump(bucket, key, timeout) // line 28
    if err != nil {
        log.Fatal("Failed to create GZIP reader")
    }
   defer gzipReader.Close()

    scanner := bufio.NewScanner(gzipReader)
    for scanner.Scan() {
        log.Printf("Read: %s
", scanner.Text())
    }

    log.Printf("Successfully download file from %s/%s
", bucket, key)
}

Aws code (aws/s3.go)

package aws

import (
    "compress/gzip"
    "context"
    "log"
    "time"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/awserr"
    "github.com/aws/aws-sdk-go/aws/request"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

func GetGZIPProductsDump(bucket, key string, timeout time.Duration) (*gzip.Reader, error) {
    sess := session.Must(session.NewSession())
    svc := s3.New(sess)

    // Create a context with a timeout that will abort the download if it takes
    // more than the passed in timeout.
    ctx := context.Background()
    var cancelFn func()
    if timeout > 0 {
        ctx, cancelFn = context.WithTimeout(ctx, timeout)
    }
    // Ensure the context is canceled to prevent leaking.
    // See context package for more information, https://golang.org/pkg/context/
    defer cancelFn()

    // Uploads the object to S3. The Context will interrupt the request if the
    // timeout expires.
    resp, err := svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
        Bucket: aws.String(bucket),
        Key:    aws.String(key),
    })
    if err != nil {
        if aerr, ok := err.(awserr.Error); ok && aerr.Code() == request.CanceledErrorCode {
            // If the SDK can determine the request or retry delay was canceled
            // by a context the CanceledErrorCode error code will be returned.
            log.Fatal("Download canceled due to timeout, %v
", err)
        } else {
            log.Fatal("Failed to download object, %v
", err)
        }
    }

    return gzip.NewReader(resp.Body) // line 47
}
  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

  • dongzhang1987 2017-04-27 08:25
    最佳回答

    The problem is related with the defer cancelFn(), currently that func is not set if the timeout is 0, this provoke a panic with a null pointer, so, you should move the defer inside of the previous if statement because it's the only point when is required to be used. The code of aws/s3.go have to be as the following.

    ...
    // Create a context with a timeout that will abort the download if it takes
    // more than the passed in timeout.
    ctx := context.Background()
    var cancelFn func()
    if timeout > 0 {
        ctx, cancelFn = context.WithTimeout(ctx, timeout)
        // Ensure the context is canceled to prevent leaking.
        // See context package for more information, https://golang.org/pkg/context/
        defer cancelFn()
    }
    ...
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题