一、项目开发流程
需求分析-->设计阶段-->实现阶段(代码)-->测试阶段-->实施阶段-->维护阶段
二、项目需求说明
1、模拟实现基于文本界面的 《家庭记账软件》
2、该软件能够记录家庭的收入、支出,并能够打印收支明细表
3、项目采用分级菜单方式,主菜单如下
三、代码实现目标
编写文件main.go 完成基本功能
1、 先可以显示主菜单,并且可以退出
2、 完成可以显示明细的功能
3、 完成登记收入的功能
4、 完成支出功能
功能1 完成主菜单及退出功能
vi main.go
package main
import "fmt"
func main() {
key := "" //声明一个变量,接收用户的选择
look := true //声明一个变量,是否退出for循环
for {
fmt.Println("-------------------------家庭收支明细-------------------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出")
fmt.Println(" 请选择1-4")
fmt.Scanln(&key) //接收用户输入
fmt.Println(key)
switch key {
case "1":
fmt.Println("-------------------------当前收支明细记录-------------------------")
case "2":
fmt.Println()
case "3":
fmt.Println("登记支出")
case "4":
look = false
default:
fmt.Println("请输入正确的选项")
}
if !look { //取反 当look不为true时触发
break
}
}
fmt.Println("您退出了家庭记账软件")
}
功能2 显示明细 登记收入
1、因为需要显示明细,我们定义一个变量details string来记录
2、还需要定义变量来记录余额(balance)\每次收支的余额(money)\每次收支的说明()
package main
import "fmt"
func main() {
key := ""
look := true
balance := 10000.0 //定义账户的余额
money := 0.0 //每次收支的金额
note := "" //每次收支的说明
//收支信息的详情,用字符串记录
//当有收支处理时,只需要对details进行拼接即可
details := "收入\t账户余额\t收支余额\t说 明"
for {
fmt.Println("\n-------------------------家庭收支明细-------------------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出")
fmt.Print(" 请选择1-4")
fmt.Scanln(&key)
fmt.Println(key)
switch key {
case "1":
fmt.Println("-------------------------当前收支明细记录-------------------------")
fmt.Println(details)
case "2": //收入登记
fmt.Println("本次收入金额")
fmt.Scanln(&money)
fmt.Println("本次收入说明")
fmt.Scanln(¬e)
balance += money //将用户的收入情况登记到总金额
//我们上面一开始定义了一个收支的面板
//这里我们将收支情况和面板1:1的形式排列进行显示
//这里换行追加到了面板下面了
details += fmt.Sprintf("\n收入\t%v\t%v\t%v",balance,money,note)
case "3":
fmt.Println("登记支出")
case "4":
look = false
default:
fmt.Println("请输入正确的选项")
}
if !look { //感叹号,取反 当look不为true时触发
break
}
}
fmt.Println("您退出了家庭记账软件")
}
功能3 完成登记支出的功能
package main
import "fmt"
func main() {
key := ""
look := true
balance := 10000.0
money := 0.0
note := ""
details := "收入\t账户余额\t收支余额\t说 明"
for {
fmt.Println("\n-------------------------家庭收支明细-------------------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出")
fmt.Print(" 请选择1-4")
fmt.Scanln(&key)
fmt.Println(key)
switch key {
case "1":
fmt.Println("-------------------------当前收支明细记录-------------------------")
fmt.Println(details)
case "2":
fmt.Println("本次收入金额")
fmt.Scanln(&money)
fmt.Println("本次收入说明")
fmt.Scanln(¬e)
balance += money
details += fmt.Sprintf("\n收入\t%v\t%v\t%v",balance,money,note)
case "3":
fmt.Println("本次支出金额")
fmt.Scanln(&money)
//关于支出必须要注意的是支出的金额不能大于总金额
if money > balance{
fmt.Println("您的余额不足")
break
}
fmt.Println("本次支出说明")
fmt.Scanln(¬e)
balance -= money
details += fmt.Sprintf("\n支出\t%v\t%v\t%v",balance,money,note)
case "4":
look = false
default:
fmt.Println("请输入正确的选项")
}
if !look {
break
}
}
fmt.Println("您退出了家庭记账软件")
}
四、代码改进
1、当用户输入4时,给出提示,您确定要退出吗?y/n
必须输入正确的y/n,否则循环输入指令,直到输入y/n
2、当没有任何收支明细时,提示"当前没有收支明细,来一笔吧"
3、 将面向过程的代码修改成面向对象的方法,编写MyFamilyAccount.go 并使用函数去测试
功能1 添加退出确认功能
package main
import "fmt"
func main() {
key := ""
look := true
balance := 10000.0
money := 0.0
note := ""
details := "收入\t账户余额\t收支余额\t说 明"
for {
fmt.Println("\n-------------------------家庭收支明细-------------------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出")
fmt.Print(" 请选择1-4")
fmt.Scanln(&key)
fmt.Println(key)
switch key {
case "1":
fmt.Println("-------------------------当前收支明细记录-------------------------")
fmt.Println(details)
case "2":
fmt.Println("本次收入金额")
fmt.Scanln(&money)
fmt.Println("本次收入说明")
fmt.Scanln(¬e)
balance += money
details += fmt.Sprintf("\n收入\t%v\t%v\t%v",balance,money,note)
case "3":
fmt.Println("本次支出金额")
fmt.Scanln(&money)
if money > balance{
fmt.Println("您的余额不足")
break
}
fmt.Println("本次支出说明")
fmt.Scanln(¬e)
balance -= money
details += fmt.Sprintf("\n支出\t%v\t%v\t%v",balance,money,note)
case "4":
fmt.Println("您确定要退出吗? y/n")
choice := ""
for {
fmt.Scanln(&choice)
if choice == "y" || choice == "n"{ //让用户必须输入一个选项才考虑退出
break
}
fmt.Println("您的输入有误,请重新输入y/n")
}
if choice == "y"{
look = false
}
default:
fmt.Println("请输入正确的选项")
}
if !look {
break
}
}
fmt.Println("您退出了家庭记账软件")
}
功能2 当没有任何收支信息时打印信息
package main
import "fmt"
func main() {
key := ""
look := true
balance := 10000.0
money := 0.0
note := ""
details := "收入\t账户余额\t收支余额\t说 明"
flag := false //定义一个变量,记录是否有收支的行为,只要操作过一次则为true
for {
fmt.Println("\n-------------------------家庭收支明细-------------------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出")
fmt.Print(" 请选择1-4")
fmt.Scanln(&key)
fmt.Println(key)
switch key {
case "1":
fmt.Println("-------------------------当前收支明细记录-------------------------")
if flag{ //添加判断
fmt.Println(details)
}else {
fmt.Println("当前没有收支明细,类来一笔吧")
}
case "2":
fmt.Println("本次收入金额")
fmt.Scanln(&money)
fmt.Println("本次收入说明")
fmt.Scanln(¬e)
balance += money
details += fmt.Sprintf("\n收入\t%v\t%v\t%v",balance,money,note)
flag = true //当有一次收入或支出时flag则为true
case "3":
fmt.Println("本次支出金额")
fmt.Scanln(&money)
if money > balance{
fmt.Println("您的余额不足")
break
}
fmt.Println("本次支出说明")
fmt.Scanln(¬e)
balance -= money
details += fmt.Sprintf("\n支出\t%v\t%v\t%v",balance,money,note)
//当有一次收入或支出时flag则为true
flag = true
case "4":
fmt.Println("您确定要退出吗? y/n")
choice := ""
for {
fmt.Scanln(&choice)
if choice == "y" || choice == "n"{
break
}
fmt.Println("您的输入有误,请重新输入y/n")
}
if choice == "y"{
look = false
}
default:
fmt.Println("请输入正确的选项")
}
if !look {
break
}
}
fmt.Println("您退出了家庭记账软件")
}
功能3 将以上面向过程的程序,变化为面向对象编程
我们上面的代码就是流水账,一条龙下来的,我们要改进为面向对象的模式
思路分析
1、把记账软件所有的功能,封装到结构体中,然后调用该结构体的方法
来实现记账,显示明细,结构体名字"FamilyAccount"
2、在main方法中,创建一个结构体"FamilyAccount"实例,来实现记账即可
vi FamilyAccount.go
package utils
import "fmt"
//定义一个结构体,声明我们全局所需的所有字段
type FamilyAccount struct{
key string //存放用户输入的选项
look bool //控制for是否退出
balance float64 //总金额
money float64 //收支数量
note string //收支说明
flag bool //是否有收支行为发生
details string //收支主页的模板
}
//编写一个工厂模式的构造方法,返回一个*FamilyAccount的实例
func NewFamilyAccount() *FamilyAccount{
return &FamilyAccount{
//赋予初始值
key: "",
look: true,
balance: 10000.0,
money: 0.0,
note: "",
flag: false,
details: "收入\t账户余额\t收支余额\t说 明",
}
}
//1、添加明细查询方法
func (this *FamilyAccount) showDetails(){
fmt.Println("-------------------------当前收支明细记录-------------------------")
if this.flag{ //添加判断
fmt.Println(this.details)
}else {
fmt.Println("当前没有收支明细,类来一笔吧")
}
}
//2、添加收入的方法
func (this *FamilyAccount) income(){
fmt.Println("本次收入金额")
fmt.Scanln(&this.money)
fmt.Println("本次收入说明")
fmt.Scanln(&this.note)
this.balance += this.money
this.details += fmt.Sprintf("\n收入\t%v\t%v\t%v",this.balance,this.money,this.note)
//当有一次收入或支出时flag则为true
this.flag = true
}
//3、添加家庭支出的方法
func (this *FamilyAccount) pay(){
fmt.Println("本次支出金额")
fmt.Scanln(&this.money)
if this.money > this.balance{
fmt.Println("您的余额不足")
}else {
fmt.Println("本次支出说明")
fmt.Scanln(&this.note)
this.balance -= this.money
this.details += fmt.Sprintf("\n支出\t%v\t%v\t%v", this.balance, this.money, this.note)
//当有一次收入或支出时flag则为true
this.flag = true
}
}
//4、 编写退出程序方法
func (this *FamilyAccount) exit(){
fmt.Println("您确定要退出吗? y/n")
choice := ""
for {
fmt.Scanln(&choice)
if choice == "y" || choice == "n"{
break
}
fmt.Println("您的输入有误,请重新输入y/n")
}
if choice == "y"{
this.look = false
}
}
//5、显示主菜单方法
func (this *FamilyAccount) MainNenu(){
//将整个for循环放进去
for {
fmt.Println("\n-------------------------家庭收支明细-------------------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出")
fmt.Print(" 请选择1-4")
fmt.Scanln(&this.key)
fmt.Println(this.key)
switch this.key {
case "1":
this.showDetails() //通过结构体调用对应的方法
case "2":
this.income()
case "3":
this.pay()
case "4":
this.exit()
default:
fmt.Println("请输入正确的选项")
}
if !this.look { //结构体
break
}
}
}
vi main.go
package main
import (
"fmt"
"go_code/jiating/utils" //注意改你本地的目录
)
func main(){
fmt.Println("这个是面向对象的创建方式")
//通过工厂模式函数去调用下面的方法
//NewFamilyAccount()创建了一个*FamilyAccount的指针实例
//通过这个实例去调用*FamilyAccount的各个方法
//通过调用MainNenu()方法,来调用其他的方法
utils.NewFamilyAccount().MainNenu()
}
效果图展示