3.30 Go 多问候语模块|Go主题月

295 阅读2分钟

  上一章节中介绍了在Go中如何返回随机的问候语。在对模块代码进行的最后修改中,您将添加对在一个请求中获取多人问候的支持。换句话说,您将处理一个多值输入,然后将该输入中的值与一个多值输出配对。

  如果直接修改greetings模块方法,则会影响到外部调用的模块hello。也即是第三方依赖你的代码会出现方法调用错误的情况,那么此时我们就不能直接修改原有方法,我们需要新增一个新的函数,可以理解为重载,便于当前代码向后做兼容。

代码编写

  1. 修改greetings.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
     }
    
     func Hellos(names []string) (map[string]string, error) {
         messages := make(map[string]string)
         for _, name := range names {
             message, err := Hello(name)
             if err != nil {
                 return nil, err
             }
             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))]
     }
    

    以上代码有了以下修改部分:

    1. 添加一个Hellos函数,它的参数是一个slice,而不是单个字符串参数。另外,您还将其返回类型从字符串更改为数组集合。
    2. 让新的Hellos函数调用现有的Hello函数。这有助于减少重复,同时保留两个函数。
    3. 创建一个消息map集合,将每个接收到的名称(作为键)与生成的消息(作为值)关联起来。在Go中,您使用以下语法初始化一个map: make(map[key-type]value-type)Hellos函数将此映射返回给调用者。有关地图的更多信息,请参阅Go博客上的Go maps in action
    4. 循环遍历函数收到的名称,检查每个名称都有一个非空值,然后将消息与每个名称关联起来。在这个for循环中,range返回两个值:循环中当前项的索引和该项值。不需要索引进行关联,因此使用Go blank标识符(下划线)来忽略它。有关更多信息,请参见Effective Go中的空白标识符
  2. 修改hello.go代码:

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

    以上代码做了以下的一个改变:

    1. 创建一个names变量作为一个包含三个名称的slice类型。
    2. names变量作为参数传递给Hellos函数。
  3. 运行以上修改过后的函数:

    [root@montos-prod hello]# go run .
     map[Darrin:Great to see you, Darrin! Gladys:Hi, Gladys. Welcome! Samantha:Hail, Samantha! Well met!]
    

总结

  上述中描述了我们如何在不破坏模块之间的依赖情况下,进行新增特性方法的调用。同时还介绍了除了slice类型之外的map数据结构。