Learning Go from documentation #5 (Last Create a module blog)

Kuzey Köse
3 min readDec 26, 2021

Blog #4 Continues

This blog is the last ‘Learning Go From documentation’ blog. In these 5 blogs, I tried to take some personal notes. So, If you are more interested, you need to check the official go documentation page. Right now, we will continue our code by greeting multiple people and adding a test. Let’s start with changing the greetings.go file to welcoming multiple people.

In blog #4, we edited the greetings.go file for selecting a random greeting. Now, handling multiple names is our task. So, we need to change greetings.go file first. Hellos function is new function to handle it. It returning parameters is little bit strange (map[string]string, error). This means that Hellos functions returns array of string.

Create a messages map to associate each of the received names (as a key) with a generated message (as a value). In Go, you initialize a map with the following syntax: make(map[*key-type*]*value-type*). You have the Hellos function return this map to the caller. For more about maps, see Go maps in action on the Go blog.

Also, Determine the messages variable for assigned values. Then, we need to loop through the names with for loop and call the Hello function for each name.

// greatings.go
package greetings
import (
"errors"
"fmt"
"math/rand"
"time"
)
func Hello(name string) (string, error) {
if name == "" {
return name, errors.New("empty name")
}
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// Hellos returns a map that associates each of the named people
// with a greeting message.
func Hellos(names []string) (map[string]string, error) {
// A map to associate names with messages.
messages := make(map[string]string)
// Loop through the received slice of names, calling
// the Hello function to get a message for each name.
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
// In the map, associate the retrieved message with
// the name.
messages[name] = message
}
return messages, nil
}
func init() {
rand.Seed(time.Now().UnixNano())
}
func randomFormat() string {
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
return formats[rand.Intn(len(formats))]
}

Let’s turn back to hello folder inside hello.go file. Now we have a opportunity that give a multiple names in Hellos function.

// hello.go
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
log.SetPrefix("greetings: ")
log.SetFlags(0)
// A slice of names.
names := []string{"Gladys", "Samantha", "Darrin"}
messages, err := greetings.Hellos(names)
if err != nil {
log.Fatal(err)
}

fmt.Println(messages)
}

Our names slice which is multiple names as an array of string (slice). These names are go inside the Hellos function and return a greetings for each. Run the function.

// terminal
$ go run .
map[Darrin:Hail, Darrin! Well met! Gladys:Hail, Gladys! Well met! Samantha:Hail, Samantha! Well met!]

Testing

So, last but not least TESTING! Go supports unit testing for easier to test as you go. Let’s turn the greeting folder and create a new file greetings_test.go.

Ending a file’s name with _test.go tells the go test command that this file contains test functions.

// greeting_test.go
package greetings
import (
"testing"
"regexp"
)
// TestHelloName calls greetings.Hello with a name, checking
// for a valid return value.
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\\b`+name+`\\b`)
msg, err := Hello("Gladys")
if !want.MatchString(msg) || err != nil {
t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
}
}
// TestHelloEmpty calls greetings.Hello with an empty string,
// checking for an error.
func TestHelloEmpty(t *testing.T) {
msg, err := Hello("")
if msg != "" || err == nil {
t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
}
}

In this code, we added test package. Then, we create two test function to test the greetings.Hello function.

Test function names have the form Test*Name*, where Name says something about the specific test. Also, test functions take a pointer to the testing package's [testing.T type](https://pkg.go.dev/testing/#T) as a parameter. You use this parameter's methods for reporting and logging from your test.

Run the code;

// terminal
$ go test
PASS
ok example.com/greetings 0.212s
$ go test -v
=== RUN TestHelloName
--- PASS: TestHelloName (0.00s)
=== RUN TestHelloEmpty
--- PASS: TestHelloEmpty (0.00s)
PASS
ok example.com/greetings 0.103s

This blog post is personal notes 🙂 If you are more interested in it, you need to check https://go.dev/doc/tutorial/greetings-multiple-people, https://go.dev/doc/tutorial/add-a-test site.

--

--