Sending SMS From Your Go app

June 19, 2014
Written by

gopherswrench

Hi, I’m Ricky, one of Twilio’s Brooklyn based Developer Evangelists. One of my favorite tips from The Pragmatic Programmer is to learn at least one new language every year. To challenge myself in 2014, I’m learning Go. There were a few things that got me excited to try Go: it’s open-source, runs on many platforms (OSX, Linux, Windows) and has an adorable gopher named Gordon as its mascot. By following this post, you will learn how to build a basic Go app that sends an SMS message using Twilio. If you like spoilers, you can look at the gist of the final code.

Recipes

Before we dive into code, there are a few dependencies you’ll need:

Need to set these up? Go ahead, I don’t mind waiting. I have some episodes of Brooklyn Nine-Nine to catch up on.

The Adventure Begins

Now that you have your tools ready to go, let’s get started. If this is your first time using Go we’ll walk through some of the basics in this post but I’d highly recommend checking out the official Go programming language tour. Here’s the initial program we’ll be starting with:

package main

import (
  "net/http"
  "net/url"
  "fmt"
  "strings"
)

func main() {
  // Set initial variables
  accountSid := "TWILIO_ACCOUNT_SID"
  authToken := "TWILIO_AUTH_TOKEN"
  urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json"
}

Every Go program starts with a package declaration. For this app we’ll be using the package name ‘main’. Next we import the other packages we’ll be using in our application. We’ll be using the net/http and net/url packages to interact with the Twilio REST API. The fmt and strings packages are used to output to the screen and manage strings. These are libraries all included in the base install. Now that we’ve imported the packages we need, we’ll start writing the code to send our SMS message using the Twilio API inside our main function. To do this we’ll be making a POST request to the Messages resource. But first we need to set our Twilio credentials so we can authenticate the request. We’ll declare two variables (accountSid and authToken) and set them to your Twilio Account Sid and Auth Token. You can find this information in your Twilio Dashboard. Next we pre-build the url string for the Messages resource. This is the url we’ll be making our POST request to. We’ll use the “url” package to prepare the POST request parameters. This package takes care of query escaping for us. Since we’ll be passing the “To”, “From” and “Body” parameters in our request we need to set them in our url.Values object Then we’ll convert that data into a new string Reader we can include in our request.

// Build out the data for our message
v := url.Values{}
v.Set("To","YOUR_PHONE_NUMBER")
v.Set("From","YOUR_TWILIO_NUMBER")
v.Set("Body","Brooklyn's in the house!")
rb := *strings.NewReader(v.Encode())

Making Your Phone Buzz

We’re almost ready to make your phone buzz. All we have left to do is make the POST request to the Twilio API. We’ll be using the Go http package to make this request.

 // Create Client
client := &http.Client{}

req, _ := http.NewRequest("POST", urlStr, &rb)
req.SetBasicAuth(accountSid, authToken)
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

First we’ll initialize a new http.Client. We initialize a new request with the method of POST, the url we want to hit (in this case the urlStr variable we defined earlier) and our post data (&rb). Next we’ll set our auth using SetBasicAuth. We’ll also make sure to set the correct Content-Type for a POST request. Now that is all ready we can call client.Do() passing our request and we’re all set. We’ll go out ahead and use fmt to print out the status so we can see if everything worked.

// Make request
resp, _ := client.Do(req)
fmt.Println(resp.Status)

This is what the code looks like when it’s put together:

package main

import (
  "net/http"
  "net/url"
  "fmt"
  "strings"
)

func main() {
  // Set initial variables
  accountSid := "TWILIO_ACCOUNT_SID"
  authToken := "TWILIO_AUTH_TOKEN"
  urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json"

  // Build out the data for our message
  v := url.Values{}
  v.Set("To","YOUR_PHONE_NUMBER")
  v.Set("From","YOUR_TWILIO_NUMBER")
  v.Set("Body","Brooklyn's in the house!")
  rb := *strings.NewReader(v.Encode())

  // Create client
  client := &http.Client{}

  req, _ := http.NewRequest("POST", urlStr, &rb)
  req.SetBasicAuth(accountSid, authToken)
  req.Header.Add("Accept", "application/json")
  req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

  // Make request
  resp, _ := client.Do(req)
  fmt.Println(resp.Status)
}

Now it’s time for the moment of the truth. Save your program as twilio.go and run it using the following command.

go run twilio.go

The program should output “201 CREATED” and you should receive a SMS message from your Twilio number.

Handling the Response

When you make a request to Twilio, we respond with some data letting you know the outcome of your request. Let’s talk about handling this response. First, we need to add two more libraries to our import. We’ll be using “io/ioutil” and “encoding/json” to read and parse the data from our response.

import (
  "net/http"
  "net/url"
  "fmt"
  "strings"
  "io/ioutil"
  "encoding/json"
)

Now let’s revisit the code that makes the request. I’ve updated this to check that the request was successful and to output the message SID for the message we sent. First, we do a conditional check on resp.StatusCode to make sure we received a 2xx response. If we didn’t, we know something went wrong and we can output the status to get more information. If we received a 2xx response, we initialize a map variable called data. This is where we’ll be storing our json data. Next we read the bytes from respBody and then use json.Unmarshal() to parse the data into our data variable. If we don’t have any errors we can output our message SID (or any other data in the response) by reading it from the data map.

// make request
resp, _ := client.Do(req)
if( resp.StatusCode >= 200 && resp.StatusCode < 300 ) {
  var data map[string]interface{}
  bodyBytes, _ := ioutil.ReadAll(resp.Body)
  err := json.Unmarshal(bodyBytes, &data)
  if( err == nil ) {
    fmt.Println(data["sid"])
  }
} else {
  fmt.Println(resp.Status);
}

Go Forth and Make Awesome Go Apps

My journey with Go is just beginning but I’m already a huge fan. I’ve been amazed with the community and the resources they provide to get new developers up to speed quickly. Whether you’re just starting or you’re a Go veteran, I hope you had as much fun building this app as I did. I can’t wait to see what awesome Go apps you all build.

Have any questions or comments? Tweet me at @rickyrobinett or e-mail me at ricky@twilio.com.