给多人问候

好了,这是最后一次修改这个模块代码, 使代码支持在一次请求问候多个人,换句话说,你将把多个输入值和内部的值匹配起来,产生多个输出值.为了达到这个目的,你需要将一组人名传入函数,然后给每个人返回问候语.

不过呢,这有一点小困难,将hello函数的入参,由单一名称改为一组名称,这叫改变函数的签名<注:我认为翻译成函数特征比较容易理解,但是其他语言都把signature叫做签名,一般来说,对于多数编程语言,函数的名称和入参共同标识了这个函数的唯一性,对于面向对象的语言,多态性就是通过改变函数参数来实现>.如果你已经将example.com/greeting模块发行,并且有人已经调用hello模块了,那么本次的改变,将会对导致他们的程序无法运行.

这这种情况下,最好的选择就是另写一个函数,并命名为其他.这个新函数将拥有多个参数,这将保留旧函数以实现向后兼容性.

在greetings/greetings.go,用下面代码替换

package greetings

import (
    "errors"
    "fmt"
    "math/rand"
    "time"
)

// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
    // If no name was given, return an error with a message.
    if name == "" {
        return name, errors.New("empty name")
    }
    // Create a message using a random format.
    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
}

// Init sets initial values for variables used in the function.
func init() {
    rand.Seed(time.Now().UnixNano())
}

// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
    // A slice of message formats.
    formats := []string{
        "Hi, %v. Welcome!",
        "Great to see you, %v!",
        "Hail, %v! Well met!",
    }

    // Return one of the message formats selected at random.
    return formats[rand.Intn(len(formats))]
}

这片代码中:

  • 增加了一个hellos函数,它的参数是一个名称切片,而不是单一名字.此外,又将返回类型从string改为map,这样你就能把问候语和名称对应起来
  • 让新的hello函数调用老的hello函数,这样能减少重复工作,并且同时保留这两个功能
  • 创建了一个messages 映射,以便将收到的名字(作为key)和产生的消息(作为value)关联,在Go中,使用下面的语法初始化一个映射: make(map[key-type] value-type). hellos函数会把这个映射返回给调用者. 更多关于maps高级知识,请参看go maps in action 
  • 遍历函数收到的名字,检查每个名字不是空值,然后给它们分派消息,在这个for-range<注:相当于foreach,>循环中返回了两个值:当前项目的索引和项目的值,其实你并不需要索引,所以就用Go 的blank标识符("_"下划线)忽略了它. 可以看看 GO本质论中的 空标识符 的细节描述

 2.在hello/hello.go代码中,传入名字切片,然后打印出返回的,名字/消息内容

package main

import (
    "fmt"
    "log"

    "example.com/greetings"
)

func main() {
    // Set properties of the predefined Logger, including
    // the log entry prefix and a flag to disable printing
    // the time, source file, and line number.
    log.SetPrefix("greetings: ")
    log.SetFlags(0)

    // A slice of names.
    names := []string{"Gladys", "Samantha", "Darrin"}

    // Request greeting messages for the names.
    messages, err := greetings.Hellos(names)
    if err != nil {
        log.Fatal(err)
    }
    // If no error was returned, print the returned map of
    // messages to the console.
    fmt.Println(messages)
}

上面代码,做了这些调整:

  • 创建了一个names变量,其类型是切片,用来装载三个名字
  • 将names变量作为参数传递给hellos函数

3.在命令行中运行代码.

原文地址:https://www.cnblogs.com/yaoshi641/p/15242641.html