Golang PutItem DynamoDB:运行时错误无效的内存地址或无指针取消引用

时间:2015-07-22 15:51:58

标签: go amazon-dynamodb aws-sdk aws-sdk-go

使用golang和AWS进行编程的新手。     我的函数中的代码块,尝试创建一个新表和写     使用AWS DynamoDB为其赋值。     创建成功,但是当Write发生时程序崩溃。     不确定为什么......如果有人能帮帮我,我真的很感激!

**Logs**:

2015/07/22 15:46:46 TableStatus: 0xc208193cb0
2015/07/22 15:46:46 End
2015/07/22 15:46:48 Sleep 2: Before Write
2015/07/22 15:46:48 Before Defining Input
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x20 pc=0x401b28]

**Code Block:**
 {
    log.Println("Entry+++")
        cfg := aws.DefaultConfig

        svc := dynamodb.New(cfg)

        tableDefinition := &dynamodb.CreateTableInput{
            TableName:            aws.String("table1"),
            AttributeDefinitions: make([]*dynamodb.AttributeDefinition, 1, 1),
            KeySchema:            make([]*dynamodb.KeySchemaElement, 1, 1),
            ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
                ReadCapacityUnits:  aws.Long(1),
                WriteCapacityUnits: aws.Long(1),
            },
        }

        tableDefinition.KeySchema[0] = &dynamodb.KeySchemaElement{
            AttributeName: aws.String("batch_id"),
            KeyType:       aws.String("HASH"),
        }
        tableDefinition.AttributeDefinitions[0] = &dynamodb.AttributeDefinition{
            AttributeName: aws.String("batch_id"),
            AttributeType: aws.String("S"),
        }

        resp, err := svc.CreateTable(tableDefinition)
        log.Println("After CreateTable---")

        if err != nil {
            log.Println("create table failed", err.Error())
            return
        }
        if resp != nil && resp.TableDescription != nil {
            log.Println(
                "TableStatus:", resp.TableDescription.TableStatus)
        }

        log.Println("End")
        //Some time before the createTable transaction gets committed. 
        time.Sleep(2 * time.Second)
        log.Println("Sleep 2 Before Write")

        testA := "batch_1" //value to be written to the db
        // testB := "batch_name"
        // testC := "530"
        // testD := "Sample-Keyy-98"

        log.Println("Before Defining Input")
        input := &dynamodb.PutItemInput{
            TableName: aws.String("table1"),
            Item: map[string]*dynamodb.AttributeValue{
                "batch_id": &dynamodb.AttributeValue{
                    S: aws.String(testA),
                },
                // "name": &dynamodb.AttributeValue{
                //  S: aws.String(testB),
                // },
            },
        }

        _, err2 := svc.PutItem(input)
    }

2 个答案:

答案 0 :(得分:2)

如果您可以显示错误的堆栈跟踪,那将非常有用。但在此之前,我可以说当您尝试访问任何未初始化变量的成员时,通常会发生此错误。 例如,如果此错误出现在以下行

a := b.c

然后你需要检查b是否正确初始化。很可能b的值是nil因此nil指针取消引用。

答案 1 :(得分:1)

Following is what I could come up with from whatever I read across the net.
Working on local secondary indexes, range index and timestamps presently.
Thanks again!    


    package main

    import (
        "github.com/aws/aws-sdk-go/aws"
        // "github.com/aws/aws-sdk-go/aws/awserr"
        "github.com/aws/aws-sdk-go/aws/awsutil"
        "github.com/aws/aws-sdk-go/service/dynamodb"

        "log"
        "strconv"
        "time"
    )

    type dynamo struct {
        db            *dynamodb.DynamoDB
        tableName     string
        readCapacity  int64
        writeCapacity int64
    }

    type metadata struct {
        dynamoDb  *dynamo
        batchID   string
        field1    string
        field2    string
        batchSize int //In Bytes
    }

    func newDynamo(name string, readCapacity, writeCapacity int64) *dynamo {
        cfg := aws.DefaultConfig
        return &dynamo{
            db:            dynamodb.New(cfg),
            tableName:     name,
            readCapacity:  readCapacity,
            writeCapacity: writeCapacity,
        }
    }

    func newMetadata(batchID, field1Val, field2Val string, batchSizeVal int) *metadata {
        return &metadata{
            batchID:   batchID,
            field1:    field1Val,
            field2:    field2Val,
            batchSize: batchSizeVal,
        }
    }

    var dynDB *dynamo
    var m *metadata

    func main() { //create the *metadata struct object, and it can then call writeToDynamo fn
        log.Println("Entry")

        dynDB = newDynamo("tableName", 1, 1) //make a new dynamo struct object
        dynDB.createTable()

        m = newMetadata("field1Value", "field2Value", 232)
        m.setDynamoDB()

        m.writeToDynamo()

        log.Println("Exit")
    }

    func (d *dynamo) createTable() (err error) {
        log.Println("createTable Entry")
        tableDefinition := &dynamodb.CreateTableInput{
            TableName: aws.String(d.tableName),
            AttributeDefinitions: []*dynamodb.AttributeDefinition{ // Required
                { // Required
                    AttributeName: aws.String("batchID"),
                    AttributeType: aws.String("S"), // Required
                },
            },
            KeySchema: []*dynamodb.KeySchemaElement{ // Required
                { // Required
                    AttributeName: aws.String("batchID"),
                    KeyType:       aws.String("HASH"), // Required
                },
            },
            ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
                ReadCapacityUnits:  aws.Long(d.readCapacity),
                WriteCapacityUnits: aws.Long(d.writeCapacity),
            },
        }

        resp, err := dynDB.db.CreateTable(tableDefinition)
        log.Println("After CreateTable---")

        if err != nil {
            log.Println("create table failed", err.Error())
            return err
        }
        if resp != nil && resp.TableDescription != nil {
            log.Println("TableStatus:", resp.TableDescription.TableStatus)
        }

        log.Println("CreateTable Exit")

        //Sleep for 15 seconds, this is better when put in a function that validates the table that was created,
        //But for testing, the program is put to sleep for 15 seconds. Program may fail if writeToDynamo is exedcuted
        //without the table being in ACTIVE state.
        time.Sleep(15 * time.Second)
        return
    }

    func (m *metadata) writeToDynamo() {
        log.Println("writeToDynamo")

        //Not exactly able to figure out what was wrong with the prev code snippet
        params := &dynamodb.PutItemInput{
            TableName: aws.String(m.dynamoDb.tableName),
            Item: map[string]*dynamodb.AttributeValue{
                "batchID": &dynamodb.AttributeValue{
                    S: aws.String(m.batchID),
                },
                "field2": &dynamodb.AttributeValue{
                    S: aws.String(m.field2),
                },
                "field3": &dynamodb.AttributeValue{
                    S: aws.String(m.field3),
                },
                "batchSize": &dynamodb.AttributeValue{
                    N: aws.String(strconv.Itoa(m.batchSize_Compressed)),
                },
            },
        }

        resp2, err2 := dynDB.db.PutItem(params)

        if err2 != nil {
            // if awsErr, ok := err2.(awserr.Error); ok { // Generic AWS error with Code, Message, and original error (if any)
            //  log.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
            //  if reqErr, ok := err.(awserr.RequestFailure); ok {
            //      // A service error occurred
            //      log.Println(reqErr.Code(), reqErr.Message(), reqErr.StatusCode(), reqErr.RequestID())
            //  }
            // } else { // This case should never be hit, the SDK should always return an //
            //  //error which satisfies the awserr.Error interface.
            //  log.Println(err2.Error())
            // }
            log.Println("Error while Writing:", err2.Error())
        }
        log.Println("Response:", awsutil.StringValue(resp2))
    }

    func (m *metadata) setDynamoDB() {
        m.dynamoDb = dynDB
    }