Go 交互式命令行工具库,提供了包括文本输入、选择菜单、确认提示、多项选择等多种交互类型,帮助快速构建交互式命令行页面。

安装

1
go get -u github.com/AlecAivazis/survey/v2

Prompt

Input 单行输入

1
2
3
4
5
var username string
prompt := &survey.Input{
Message: "Input username:",
}
survey.AskOne(prompt, &username)

可以通过设置 Suggest 来给用户提供建议,帮助补全输入, Suggest 为由当前输入值返回建议值列表的方法。如下面补全文件路径示例。

1
2
3
4
5
6
7
8
9
var path string
prompt := &survey.Input{
Message: "Input file path:",
Suggest: func(toComplete string) []string {
files, _ := filepath.Glob(toComplete + "*")
return files
},
}
survey.AskOne(prompt, &path)

Multiline 多行输入

Select 单选

1
2
3
4
5
6
var tool string
prompt := &survey.Select{
Message: "Choose a tool:",
Options: []string{"toolA", "toolB", "toolC"},
}
survey.AskOne(prompt, &tool)

可以通过设置 Description 给每个选项添加描述, Description 为由选项值/序号返回描述的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var tool string
description := map[string]string{
"toolA": "Description for toolA",
"toolB": "Description for toolB",
"toolC": "Description for toolC",
}
prompt := &survey.Select{
Message: "Choose a tool:",
Options: []string{"toolA", "toolB", "toolC"},
Description: func(value string, index int) string {
return description[value]
},
}
survey.AskOne(prompt, &tool)

MultiSelect 多选

1
2
3
4
5
6
days := []string{}
prompt := &survey.MultiSelect{
Message: "What days do you prefer:",
Options: []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
}
survey.AskOne(prompt, &days)

Confirm 确认

1
2
3
4
5
answer := false
prompt := &survey.Confirm{
Message: "Are you sure to continue?",
}
survey.AskOne(prompt, &answer)

Password 密码

1
2
3
4
5
password := ""
prompt := &survey.Password{
Message: "Please type your password",
}
survey.AskOne(prompt, &password)

Option

Validator

设置输入验证,提供输入验证函数(输入:输入值,返回 error),如果用户输入验证不通过,则提示错误,并重新提问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var input string
prompt := &survey.Input{
Message: "Input number:",
}
// 验证输入为数字,并在0到10范围内
vaildInputNumber := func(val interface{}) error {
num, err := strconv.Atoi(val.(string))
if err != nil {
return fmt.Errorf("not number")
}
if num < 0 || num > 10 {
return fmt.Errorf("not in 0~10")
}
return nil
}
survey.AskOne(prompt, &input, survey.WithValidator(vaildInputNumber))

Survey 库也提供了一些可直接调用的验证函数

  • Required :要求非空
  • MinLength(n) :最小长度
  • MaxLength(n):最大长度
  • Ask

    Ask 支持连续问多个问题,设置多个问题,每个问题可以包括四个部分:

  • Name :与回答结构体里的元素对应,用于指名结果解析到哪个元素
  • Prompt :具体的问题
  • Vaildate :回答的验证方法
  • Transform :自动更改格式
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    qs := []*survey.Question{
    {
    Name: "name",
    Prompt: &survey.Input{Message: "What is your name?"},
    Validate: survey.Required,
    Transform: survey.Title,
    },
    {
    Name: "color",
    Prompt: &survey.Select{
    Message: "Choose a color:",
    Options: []string{"red", "blue", "green"},
    Default: "red",
    },
    },
    {
    Name: "age",
    Prompt: &survey.Input{Message: "How old are you?"},
    Validate: func(val interface{}) error {
    _, err := strconv.Atoi(val.(string))
    if err != nil {
    return fmt.Errorf("not number")
    }
    return nil
    },
    },
    }

    answers := struct {
    Name string // survey will match the question and field names
    FavoriteColor string `survey:"color"` // or you can tag fields to match a specific name
    Age int // if the types don't match, survey will convert it
    }{}

    // perform the questions
    err := survey.Ask(qs, &answers)
    if err != nil {
    fmt.Println(err.Error())
    return
    }
  • https://github.com/AlecAivazis/survey
  • https://pkg.go.dev/github.com/AlecAivazis/survey/v2#section-readme
  •