参考:https://go.dev/doc/tutorial/random-greeting
在这一部分,你将改变你的代码,以便于能替换每次返回单个的问候语,它返回若干个提前定义好的问候语中的一个。
为了做到这样的事情,你将使用一个Go的切片。一个切片像一个数组,除了当你添加或移除项目的时候,它的大小能够动态的改变。切片是Go中非常有用的数据类型。
你将添加一个小的切片,去包含三个问候语,然后你的代码从中返回其中的一个。关于切面的更多内容,可以看Go切片文章。
在greetings/greeting.go文件中,改变你的代码,以至于它看起来像下面:
package greetings
import (
"errors"
"fmt"
"math/rand"
"time"
)
// Hello 为一个命名的人返回一个问候
func Hello(name string) (string, error) {
// 如果没有给出name,返回一个带有消息的错误
if name == "" {
return "", errors.New("empty name")
}
// 如果接受到一个名字,返回一个问候,嵌套名字在消息中
// message := fmt.Sprintf("Hi, %v. Welcome!", name)
// 使用随机消息格式创建消息
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// 为在函数中使用的变量初始化集合的最初始的值
func init() {
rand.Seed(time.Now().UnixNano())
}
// randomFormat 返回一个问候语集合中的一个,被返回的消息是随机选择的
func randomFormat() string{
// 一个消息格式的切片
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// 根据指定的随机索引从格式化切片中返回一个随机选择的消息格式
return formats[rand.Intn(len(formats))]
}
在这个代码中:
randomFormat函数,它能为问候消息返回一个随机选择的格式。注意randomFormat使用了小写字母开始,让它仅能让在自己包中的代码访问(换句话说,它不出口)。randomFormat中,使用三个消息格式声明了一个formats 切片。当声明一个切片的时候,在声明一个切片的时候,你在中括号中忽略了它的大小,就像[]string。这是告诉Go,切片内部的数组大小能够动态改变。math/rand 包去生成一个随机数字。init函数,使用当前的时间去播种rand包。在程序启动的时候,在全部变量被初始化之后,Go会自动执行init函数。Hello中,调用randomFormat函数去获取一个你将返回的消息格式,然后一起使用格式和name值去创建一个消息。在hello2/hello2.go文件中,改变你的代码以至于它看起来像下面:
将hef作为参数给Hello函数,在hello2.go 中进行调用。
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// 设置Logger预定义的属性,包含了log项的前缀,和一个禁用打印时间,源文件,行号的标识。
log.SetPrefix("greetings: ")
log.SetFlags(0)
// 获取一个问候消息,并打印它
// message := greetings.Hello("hef")
// 请求一个问候消息
// message, err := greetings.Hello("")
message, err := greetings.Hello("hef")
// 如果一个错误返回,将它打印到控制台,并退出程序
if err != nil {
log.Fatal(err)
}
// 如果没有错误返回,打印返回到消息到控制台
fmt.Println(message)
}
在hello2目录的命令行中,运行hello2.go去验证代码的工作。多次运行它,注意问候的改变
$ go run .
Great to see you, hef!
$ go run .
Hail, hef! Well met!
$ go run .
Hi, hef. Welcome!