本文讲解如何正确设计泛型风格的输入函数,通过类型断言和指针传递实现对 string 和 int 类型的安全扫描,避免常见 panic 和逻辑错误。
本文讲解如何正确设计泛型风格的输入函数,通过类型断言和指针传递实现对 string 和 int 类型的安全扫描,避免常见 panic 和逻辑错误。
在 Go 中,fmt.Scanf 并不支持直接扫描值类型变量(如 string 或 int),而必须传入对应类型的指针——这是初学者常踩的坑。你提供的原始代码存在两个关键问题:一是 default 分支位置错误导致其他 case 永远无法执行;二是 input 是值而非地址,Scanf 无法写入目标变量。
✅ 正确实现方式
需将函数参数改为接收指针,并在 switch 中匹配 *int 和 *string 类型:
func getUserInput(input interface{}) error {
var err error
switch t := input.(type) {
case *int:
_, err = fmt.Scanf("%d", t)
case *string:
_, err = fmt.Scanf("%s", t)
default:
return fmt.Errorf("unsupported type: %T", t)
}
return err
}调用时务必传入变量地址:
var firstName string
fmt.Print("Enter name: ")
if err := getUserInput(&firstName); err != nil {
log.Fatal(err)
}
fmt.Printf("Name: %s\n", firstName)
var age int
fmt.Print("Enter age: ")
if err := getUserInput(&age); err != nil {
log.Fatal(err)
}
fmt.Printf("Age: %d\n", age)⚠️ 注意事项与进阶建议
- 类型顺序很重要:default 必须放在 case 之后,否则会提前截断匹配;
- Scanf 的局限性:%s 遇到空格即停止,若需读取含空格的字符串,请改用 bufio.Scanner;
- 更健壮的替代方案(推荐):先读取完整行,再尝试解析,便于错误诊断与多类型兼容:
func readInput() (string, error) {
reader := bufio.NewReader(os.Stdin)
line, err := reader.ReadString('\n')
return strings.TrimSpace(line), err
}
// 使用示例:
line, _ := readInput()
if age, err := strconv.Atoi(line); err == nil {
// 成功解析为 int
} else if len(line) > 0 {
// 视为字符串
}这种模式不仅避免了 Scanf 的格式依赖和副作用,还能统一处理输入、提供清晰错误信息,是生产环境中更可靠的选择。


















