Creating a Go module
Creating a Go module
We’re going to create a CLI tool for sending a message to a channel in Slack using the command line. This post is similar to my earlier post: Creating an Elixir Module. We’ll be using the chat.postMessage Slack API endpoint. Also, make sure you have a Slack API token.
Our CLI syntax will be:
$ ./slack -message 'hello world!' -channel @slackbot
First, make sure you have your $GOPATH
set properly.
export GOPATH="/path/to/go/"
Next, set your Slack token as an environment variable:
export SLACK_TOKEN=<token>
Typically, developers will use one folder for all of their Go code, and create new folders within for each new project. My structure looks like this:
go ├── bin ├── pkg └── src
Make a folder called slack
within src
, then inside that folder create the following files and folders as well:
slack/ ├── api │ └── slack.go └── main.go
Using the builtin Go command line parser flag
, we will write our main.go
file to parse the message and channel from the command line.
slack/main.go
package main
import ( "slack/api" "flag")
func main() { msg := flag.String("message", "", "The `message` to send the `channel`") channel := flag.String("channel", "", "The `channel` to send the `message`") flag.Parse() api.SendMsg(*msg, *channel)}
This sets us up with a CLI parser which will take our provided arguments and pass them to the SendMsg
function, which we will define now.
Make sure you have set the environment variable SLACK_TOKEN
with your token.
slack/api/slack.go
package api
import ( "fmt" "net/http" "net/url" "os")
const slackUrl string = "https://slack.com/api/"const chatPostMsg string = "chat.postMessage"
func SendMsg(msg, channel string) { token := getToken() // keys and values for query string parameters used in the API call paramMap := map[string]string{ "token": token, "as_user": "true", "text": msg, "channel": channel, } url := buildUrl(slackUrl+chatPostMsg, paramMap) resp, err := http.Post(url, "application/json", nil) // handle and error calling `http.Post` if err != nil { fmt.Println(err) fmt.Println("failed to post") } // handle non-200 status codes if resp.StatusCode == 200 { fmt.Println("Sent message!") fmt.Println(fmt.Sprintf("%s <- %s", channel, msg)) } else { fmt.Println("Failed to send message.") fmt.Println(resp) }}
// Build the URL using the parameters map and builtin URL libraryfunc buildUrl(urlString string, args map[string] string) string { u, err := url.Parse(urlString) if err != nil { fmt.Println("Error parsing URL string") } v := url.Values{} for key, value := range args { v.Set(key, value) } u.RawQuery = v.Encode() return u.String()}
// check that token is set in environmentfunc getToken() string { token := os.Getenv("SLACK_TOKEN") if token == "" { fmt.Println("Environment variable `SLACK_TOKEN` not set") fmt.Println("Set with:") fmt.Println("\texport SLACK_TOKEN=<token>") panic("Exiting") } return token}
With these two files written, we can go the to slack
folder and test the program:
$ go run main.go -channel @slackbot -message 'hello!'
If all goes well, you will see the output:
Sent message!@slackbot <- hello!
and the message will show up from you to slackbot in the Slack app.
To build the program as a standalone, distributable binary run:
$ go build -o slack
This creates a binary file called slack
in the folder, which can be run with:
$ ./slack -message 'hello world!' -channel @slackbot
That’s it!
Thanks to Hans Li for the help with testing!
Recommended
Creating an Elixir module
Creating an Elixir module
Go scope
Scoping in Go is built around the notion of code blocks. You can find several good explanations of how variable scoping work in Go on Google. I'd...
Debugging go code with delve
Delve is a debugger for the Go programming language. The goal of the project is to provide a simple, full featured debugging tool for Go.