This enables allows you to code functions using Golang 1.23. The
handle function defines the HTTP request handler logic. This
function must implement the logic that the function should execute each time it is
invoked.
package function
import (
"io/ioutil"
"net/http"
)
// Handle defines the logic of the HTTP request handler.
//
// This example echoes the HTTP request payload by returning a response with
// status code 200 and the same payload used in the request.
func Handle(w http.ResponseWriter, r *http.Request) {
var body []byte
if r.Body != nil {
defer r.Body.Close()
body, _ = ioutil.ReadAll(r.Body)
}
w.WriteHeader(http.StatusOK)
w.Write(body)
}
The Handle function is the HTTP Handler in which your code will run. You can use other functions in your
code to make it cleaner, but the Handle function is the entry point
of your serverless function. Check these sources for further information about Go
handlers:
Any library can be added to a Function for Go templates. to add a library, click on
the + Add Library button and fill in the name (required) and
version (optional).Figure 1.
There are no required libraries.
The name of the library can be any in the recommended library list.
For custom libraries:
name needs to be the same as the name of the package (for
example, github.com/spf13/viper).
If a library is in the recommended library list, the name can be the alias
(for example, testify) or the full name (such as
github.com/stretchr/testify).
Non-required libraries can have any version. If version is
omitted:
The predefined version will be used for recommended libraries.
For other libraries, the latest available version will be used.
The list of recommended libraries consists of:
resty: A simple HTTP and REST client library for
Go.
Here are some simple examples to illustrate how you can write your own functions
using Go.
Adder
This is a really simple function that gets a comma-separated list of
numbers in the request body and return the sum of them (or an error if
the input format is invalid).
package function
import (
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
)
func Handle(w http.ResponseWriter, r *http.Request) {
var body []bytevar sum float64 = 0
//Gets function inputif r.Body != nil {
defer r.Body.Close()
body, _=ioutil.ReadAll(r.Body)
}
// Parses input as a comma-separated list of numbers
numbers := strings.Split(string(body), ",")
//Tries to convert all values to numbersfor _, number :=range numbers {
number = strings.TrimSpace(number)
if value, err :=strconv.ParserFloat(number, 32); err != nil {
//Throws an error if something is not a number
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Invalid input format!"))
return
} else {
sum += value
}
}
w.WriterHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("%f", sum)))
}
MQTT Publisher
The following example shows how to set up an MQTT client to publish the
payload of the request to the functions/go topic.
package function
import (
"fmt"
mqtt "github.com/eclipse/paho.mqtt.golang"
"io/ioutil"
"net/http"
)
const (
MQTTBroker = "test.mosquitto.org"
MQTTPort = 1883
)
func Handle(w http.ResponseWriter, r *http.Request) {
var input []byte
if r.Body != nil {
defer r.Body.Close()
input, _ = ioutil.ReadAll(r.Body)
}
opts := mqtt.NewClientOptions()
opts.AddBroker(fmt.Sprintf("tcp://%s:%d", MQTTBroker, MQTTPort))
client := mqtt.NewClient(opts)
if token := client.Connect(); token.Wait() && token.Error() != nil {
panic(token.Error())
}
t := client.Publish("functions/go", 0, false, input)
<-t.Done() // Wait until message is published
if t.Error() != nil {
panic(t.Error())
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Message published!"))
}
Update a Thing's Property
The following example shows how to update a Thing's Property using the
swx package to deal with token request and
revocation.
package function
import (
"fmt"
"function/swx"
"function/swx/auth"
"io/ioutil"
"net/http"
"github.com/go-resty/resty/v2"
)
// We'll use a Thing credentials to request the access token
var (
ApiUrl = "https://api.swx.altairone.com"
Space = "examples" // Change it to your Space name
Category = "<A-CATEGORY-NAME>"
ThingID = "<A-THING-ID>"
ClientID = "<A-CLIENT-ID>"
)
func Handle(w http.ResponseWriter, r *http.Request) {
// Get the client secret from the Secrets Storage.
// This avoids hardcoding the secret in the code.
clientSecret := secrets.Get("my_secret_name")
token, err := auth.GetToken(ClientID, clientSecret, []string{"thing.update"})
if err != nil {
w.WriteHeader(err.(*swx.OAuth2Error).Err.Status)
return
}
defer token.Revoke() // This ensures the token is revoked before the function ends
url := fmt.Sprintf("%s/spaces/%s/collections/%s/things/%s/properties",
ApiUrl, Space, Collection, ThingID)
client := resty.New()
resp, err := client.R().
SetAuthToken(token.AccessToken).
SetBody(map[string]interface{}{"temperature": 27}).
Put(url)
if err != nil {
w.WriteHeader(resp.StatusCode())
w.Write(resp.Body())
return
}
w.WriteHeader(http.StatusOK)
w.Write(resp.Body())
}