Todays post will begin to use the specific AWS specific commands, and in doing so, introduce further areas such as returned values, blank identifiers, obtaining the value from a pointer location, nil, and also conditional statements. By the end of this, we’ll be able to compile and run the code, achieving our goal of being able to upload a file to an S3 bucket.

Create a New Upload Session

Now we’re also getting into AWS side of things. In this, we create a new session, storing it in the sess variable. We then also use this variable to create a new uploader object.

1

2

3

4

sess,_:=session.NewSessionWithOptions(session.Options{

Config:aws.Config{Region:aws.String("eu-west-1")},

Profile:"development",

})

There’s quite a few things going on here in this part as well, despite it only being two commands.

You’ll probably have already noticed the := operator, mentioned in the previous section of code. What’s different this time though is that there is a comma and _ character on the left hand side as well.

In Go, the output from a function is carried out via the return command. Unlike some other languages, in Go if you wish to return more than one value, it does not need to be ‘packaged’ up into an object you later have to parse. Instead, you define one or more names (solely for use within the function), with types to be returned in your function header. At the exit point of the function, you simply use the return statement along with the variables being returned that match up with the declaration. A comma is used to separate these. e.g. return x, y

In some circumstances you may not be interested in a specific return value from a function. However, In Go we can use _ also known as a blank identifier, when the program logical requires a value to be returned, but we do not want to use this value.

With reference to the above code, a quick look at the documentation for session.NewSessionWithOptions function tells us it returns both a session object, but also an error object. So in the code above, we are simply receiving, but discarding, the error details returned.

Go

1

uploader:=s3manager.NewUploader(sess)

Now define uploader, which will allow us to use the variable upload functions for upload to S3.

Validate the File Exists

We want to make sure that the filename being referred to actually exists before attempting any upload. If the file does not exist, then we want to display the error message, and then exit the program. We use the os.Open function to test this.

Go

1

2

3

4

5

6

file,err:=os.Open(*filename)

iferr!=nil{

fmt.Println(err.Error())

os.Exit(1)

}

We now use both variables returned by os.Open

What does *filename mean? Well, remember when we assigned this variable, it was pointer that was returned, not a value. If we were to pass it in a filename, all we would be passing it would be a memory address. To tell Go to pass in the value at the memory address, we prefix this with a *

Next, we check what err is set to. We does this via the if err != nil condition

The equivalent of is not equal to in go is !=

An uninitialized value in Go is referred to as nil, mostly akin to null in other programming languages.

Thus, our condition could read “if the value of err is not unitialized”

The actions to be undertaken if the condition above is true is carried out within the {….} block

Use fmt.Println to output to the console the err.Error, which contains the error text

Exit the program using os.Exit, returning the error code of 1 back.

Upload the File

The final part is to carry out the upload of the object to an S3 bucket, check if the task has completed successfully.

Go

1

2

3

4

5

6

7

8

9

10

11

key:=filepath.Base(file.Name())

_,err=uploader.Upload(&s3manager.UploadInput{

Bucket:aws.String(*bucket),

Key:aws.String(key),

Body:file,

})

iferr!=nil{

fmt.Println(err)

}

First, we define the value of key. Remember that in S3, there is no such thing as either a file, or a directory. However, we are able to define a key, which will be used for referencing it. On this occasion, we simply set the value of key to the name of the file.

On this occasion, we’re only interested if there’s an error occurred, as opposed to the other output of the function.

We use the upload.Upload function, supplying it with a pointer to a memory location holding a collection of the type UploadInput, which is in turn a struct.

A struct is quite simply a collection of names and values, akin to what we sometimes call hashtables in other languages.

In our case, we are submitting values in the struct for Bucket, Key, and Body.

What does & mean? In Go, prefixing a variable with an ampersand instructs it to use the memory location of it, as opposed the a value. upload.Upload expects a pointer as the parameter.

Finally, we check err in exactly the same manner as previous in the code, outputting the error, if one occurs.

Compiling the code

That’s us finished our first program for AWS in Go! The next step is to compile the program itself.

Start a terminal session and change your current directory to the one in which the .go file is
To carry out the compile action, generating the executable, enter the following :-

Go

1

gobuild

Building a Go package requires compiling .go in a directory structure. We use the go build statement for that.

By default, go build uses an output name that is the same as the .go file without the suffix.

This command can be overwritten using -o xxxx, where xxxx is the name of the file you wish generated.

You should see output similar to that of below:

Checking the Help Text

Forgotten how we use the command? If we want to get the help text for the package we’ve just compiled, we can just use:

Shell

1

./upload--help

Giving us the following:
Seem familiar to some code from a blog or two ago?

Running the Code

Let’s run our executable now, using a file I’ve got on my desktop.

Validating Upload

Conclusion

In this post we’ve seen how values and returned from functions and how we can use them, the use of blank identifiers to ignore information we don’t need returned, obtaining values from a pointer location, the use of nil, conditional statements, and how to compile a package. Lastly, we found out how to get help on a compiled package, and run it with parameters.

This is the first part of our three stage project out of the way. In the next part, and similar to the PowerShell blog post, we’re going to be developing code which will create a Transcribe job, using a media file we’ve uploaded to S3.

However, we’re going to make it much more funky and automagic. So in addition to Transcribe, we’ll be using S3 events, and Lambda. By the end of it, we’ll have a system in place that just requires us to drop a mp4 file into a bucket and through the wonders of Lambda, a Transcribe job will be automatically created for us.