New to programming with golang and AWS. Block of code in my function, trying out creating a new table and writing values to it using AWS DynamoDB. Creation is successful, but the program crashes when the Write happens. Not sure why..I'd be really grateful if anyone could help me out!
**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)
}
It would be very helpful if you could show the stack trace of error. But until then i could say that this error usually occurs when you try to access member of any uninitialized variable. For example if this error is comming at following line
a := b.c
then you need to check if b is initialized properly. Most probably value of b is nil hence nil pointer dereference.
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
}