Golang中Scan和Scanln的区别是什么

Golang中Scan和Scanln的区别是什么 我是一名刚开始学习Go语言的学生。这是我今天遇到的一个问题。

import "fmt"

func main() {
	var key string
	loop := true
	balance := 10000.0
	money := 0.0
	note := ""
	details := "收支\t账户金额\t收支金额\t说明"

	for {
		fmt.Println("\n--------------------家庭收支记账软件-------------------")
		fmt.Println("                  1 details")
		fmt.Println("                  2 input")
		fmt.Println("                  3 withdraw")
		fmt.Println("                  4 exit")
		fmt.Println()
		fmt.Println("               please choice(1-4):")

		fmt.Scanln(&key)

		switch key {
		case "1":
			fmt.Println("--------------------details-------------------")
			fmt.Println(details)
		case "2":
			fmt.Println("input for this time:")
			fmt.Scan(&money)
			fmt.Println("note for this time:")
			fmt.Scan(&note)
			balance += money
			details += fmt.Sprintf("\ninput\t%v\t%v\t%v", balance, money, note)
		case "3":
			fmt.Println("登记支出...")
		case "4":
			loop = false
		default:
			fmt.Println("it`s not right")
		}
		if !loop {
			break
		}

	}
	fmt.Println("you have exit")

}

这是我的代码。 当它启动时,我输入2,然后输入金额和备注, 然后,它又从2开始循环,就像这样:

QQ截图20220226200556

但是,如果我使用 Scanln 而不是 Scan(即 fmt.Scanln(&money)fmt.Scanln(&note)),它就能正常工作。 为什么? 希望有好心人能帮助我。


更多关于Golang中Scan和Scanln的区别是什么的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

谢谢!我之前读过 fmt 包的内容,但我还是不明白。我只想输入一个“3”,不要有空格。

更多关于Golang中Scan和Scanln的区别是什么的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于 note 变量没有获取到你输入的所有单词?fmt.Scan 在遇到空格后会停止读取输入(标准输入)。

favicon.ico

fmt 包 - fmt - pkg.go.dev

fmt 包实现了格式化 I/O,其函数类似于 C 语言中的 printfscanf

你可能希望将整行(包括空格)读取到 note 变量中:

favicon.ico

fmt 包 - fmt - pkg.go.dev

fmt 包实现了格式化 I/O,其函数类似于 C 语言中的 printfscanf

你的意思是不想在备注后面换行吗?

你是在循环开始处打印的,把它去掉

	for {
                // 下面的 Println 中不要打印换行
		fmt.Println("--------------------家庭收支记账软件-------------------")
		fmt.Println("                  1 收支明细")
		fmt.Println("                  2 登记收入")
		fmt.Println("                  3 登记支出")
		fmt.Println("                  4 退出")
		fmt.Println()
		fmt.Println("               请选择(1-4):")

		fmt.Scanln(&key)

		switch key {
		case "1":
			fmt.Println("--------------------收支明细-------------------")
			fmt.Println(details)
		case "2":
			fmt.Println("本次收入金额:")
			fmt.Scan(&money)
			fmt.Println("本次收入说明:")
			fmt.Scanln(&note)
			balance += money
			details += fmt.Sprintf("\n收入\t%f\t%f\t%s", balance, money, note)
			fmt.Printf("备注是:" + "'" +note + "'" + "\n")

在Go语言中,fmt.Scanfmt.Scanln的主要区别在于它们处理输入缓冲区中换行符的方式。

关键区别:

  • Scanln:读取输入直到遇到换行符,并丢弃该换行符
  • Scan:读取输入但不会自动丢弃换行符,换行符会留在输入缓冲区中

在你的代码中,当使用fmt.Scan(&money)读取金额后,输入缓冲区中仍然保留着换行符。接着执行fmt.Scan(&note)时,它会立即遇到这个换行符,将其解释为空输入,导致note变量获取不到值,程序继续执行。

示例代码说明:

package main

import "fmt"

func main() {
    // 使用Scan的问题示例
    var money float64
    var note string
    
    fmt.Print("输入金额: ")
    fmt.Scan(&money)  // 输入"100"后按回车
    
    fmt.Print("输入备注: ")
    fmt.Scan(&note)   // 这里会立即读取到缓冲区中的换行符
    
    fmt.Printf("金额: %v, 备注: '%s'\n", money, note)
    // 输出: 金额: 100, 备注: ''
}

// 使用Scanln的正确示例
func exampleWithScanln() {
    var money float64
    var note string
    
    fmt.Print("输入金额: ")
    fmt.Scanln(&money)  // 读取"100"并丢弃换行符
    
    fmt.Print("输入备注: ")
    fmt.Scanln(&note)   // 可以正常读取用户输入
    
    fmt.Printf("金额: %v, 备注: '%s'\n", money, note)
    // 输出: 金额: 100, 备注: '工资'
}

// 如果必须使用Scan,可以添加额外的读取来清除换行符
func exampleWithScanFixed() {
    var money float64
    var note string
    
    fmt.Print("输入金额: ")
    fmt.Scan(&money)
    
    // 清除输入缓冲区中的换行符
    var discard string
    fmt.Scanln(&discard)
    
    fmt.Print("输入备注: ")
    fmt.Scan(&note)
    
    fmt.Printf("金额: %v, 备注: '%s'\n", money, note)
}

在你的记账软件中,使用Scanln是正确的选择,因为它能正确处理行尾的换行符,确保每次读取都能获取到用户的完整输入。

回到顶部