【Golang第9章:项目练习】go项目练习家庭收支记账软件项目、go项目练习客户管理系统项目

介绍

这个是在B站上看边看视频边做的笔记,这一章是Glang面向对象编程的项目练习

配套视频自己去B站里面搜【go语言】,最高的播放量就是

里面的注释我写的可能不太对,欢迎大佬们指出╰(°▽°)╯

(九)、项目练习

一、家庭收支记账软件项目

1.项目开发流程说明

在这里插入图片描述





2.项目需求说明

  1. 模拟实现基于文本界面的《家庭记账软件》
  2. 该软件能够记录家庭的收入、支出,并能够打印收支明细表




3.项目的界面

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述





4.项目代码实现

1)实现功能

  • 功能1:先完成可以显示主菜单,并且可以退出

  • 功能2:完成可以显示明细登记收入的功能

  • 功能3:完成了登记支出的功能

    思路分析:

    更加给出的界面完成,主菜单的显示, 当用户输入4 时,就退出该程序

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	userKey := ""    //声明key变量,用来接收用户输入的值
    	userexit := true //用来控制for循环退出
    	balance := 0.0   //账号初始余额
    	money := 0.0     //账号每次收支金额---用户接收最好只能使用string类型,千万不要使用其他类型---
    	note := ""       //账号收支说明
    	details := fmt.Sprintf("%-10v  %-11v  %-12v  %-11v",
    		"收支", "账户金额", "收支金额", "说    明") //收支明细,当有收支是,只需要对details进行拼接处理
    
    	record := false //检测有没有支出
    
    	for { //账号主菜单显示
    		fmt.Printf("\033[1;32;40m%s\033[0m\n", "---------家庭收支 记账软件---------")
    		fmt.Println()
    		fmt.Printf("\033[1;32;40m%s\033[0m\n", "         1 收支明细")
    		fmt.Printf("\033[1;32;40m%s\033[0m\n", "         2 登记收入")
    		fmt.Printf("\033[1;32;40m%s\033[0m\n", "         3 登记支出")
    		fmt.Printf("\033[1;32;40m%s\033[0m\n", "         4 退出")
    		fmt.Println()
    		fmt.Printf("\033[1;32;40m%s\033[0m\n", "请选择(1-4):")
    		fmt.Scanln(&userKey) //接收用户输入参数
    
    		switch userKey {
    		case "1":
    			fmt.Printf("\033[1;32;40m%s\033[0m\n", "---------当前收支 明细记录---------")
    			if record {
    				fmt.Println(details)
    			} else {
    				fmt.Println("当前没有支出记录")
    			}
    
    			fmt.Println()
    			userKey = ""
    		case "2":
    			//
    			fmt.Printf("\033[1;32;40m%s\033[0m\n", "登记收入金额:")
    			fmt.Scanln(&money)
    
    			if money == 0 {
    				fmt.Printf("\033[1;31;40m%s\033[0m\n", "输入金额有误,请重新输入...")
    				break
    			}
    			value1 := true
    			for i, v := range fmt.Sprintf("%.4f", money) {
    
    				if i == 0 && v == 46 {
    					value1 = false
    					break
    				} else if v < 46 || v > 57 || v == 47 {
    					value1 = false
    					break
    				}
    			}
    			if value1 {
    				if len(fmt.Sprintf("%v", money))-5 > 9 {
    					fmt.Printf("\033[1;31;40m%s\033[0m\n", "输入金额过大,你太有钱了。。")
    					userKey = ""
    					break
    				} else {
    					balance += money //修改balance
    					fmt.Printf("\033[1;32;40m%s\033[0m\n", "收入情况说明:")
    					fmt.Scanln(&note)
    
    					//将收入情况拼接到details变量
    					details += fmt.Sprintf("\n%-10s  %-15.4f  +%-15.4f  %-10s",
    						"收入", balance, money, note)
    
    					record = true
    				}
    			} else {
    				fmt.Printf("\033[1;31;40m%s\033[0m\n", "输入有误,请重新输入...")
    				userKey = ""
    				break
    			}
    			//
    
    			userKey = ""
    
    		case "3":
    			//
    			fmt.Printf("\033[1;32;40m%s\033[0m\n", "登记支出金额:")
    			fmt.Scanln(&money)
    			if money > balance {
    				fmt.Printf("\033[1;31;41m%s\033[0m\n", "账户余额不足")
    				break //检测到余额不足时直接退出,后面将不再执行
    			}
    			balance -= money
    			fmt.Printf("\033[1;32;40m%s\033[0m\n", "支出情况说明:")
    			fmt.Scanln(&note)
    
    			//将收入情况拼接到details变量
    			details += fmt.Sprintf("\n%-10s  %-15.4f  -%-15.4f  %-10s",
    				"收入", balance, money, note)
    			record = true
    			//
    			userKey = ""
    		case "4":
    			fmt.Println("真的要退出吗? y/n")
    			yOrn := ""
    
    			for {
    				fmt.Scanln(&yOrn)
    				if yOrn == "y" || yOrn == "n" {
    					break
    				}
    				fmt.Println("输入有误,请输入 y/n")
    			}
    			if yOrn == "y" {
    				userexit = false //把userexet改为假false
    			} else {
    				userexit = true
    			}
    
    			userKey = ""
    		default:
    			fmt.Printf("\033[1;31;40m%s\033[0m\n", "输入有误,请重新输入...")
    			userKey = ""
    		}
    
    		if !userexit { //判断userexit是否为假,如果为假则break退出for循环
    			break
    		}
    	}
    }
    




2)面向过程修成面向对象

将面向过程的代码修改成面向对象的方法, 编写myFamilyAccount.go , 并使用testMyFamilyAccount.go去完成测试

思路分析:

把记账软件的功能,封装到一个结构体中,然后调用该结构体的方法,来实现记账,显示明细。结构体的名字FamilyAccount .

在通过在main 方法中,创建一个结构体FamilyAccount 实例,实现记账即可.

代码:

familyAccount.go

package utils

import "fmt"

type FamilyAccount struct {
	userKey  string
	userexit bool
	balance  float64
	money    float64
	note     string
	details  string

	record bool //检测有没有支出
}

//编写要给工厂模式的构造方法,返回一个*FamilyAccount实例
func NewFamilyAccount() *FamilyAccount {
	return &FamilyAccount{
		userKey:  "",
		userexit: true,
		balance:  0.0,
		money:    0.0,
		note:     "",
		details: fmt.Sprintf("%-10v  %-11v  %-12v  %-11v",
			"收支", "账户金额", "收支金额", "说    明"), //收支明细,当有收支是,只需要对details进行拼接处理
		record: false,
	}
}

//给该结构体绑定对于的方法
//显示主菜单
func (this1 *FamilyAccount) MainMeum() {
	for { //账号主菜单显示
		fmt.Println("---------家庭收支 记账软件---------")
		fmt.Println()
		fmt.Println("         1 收支明细")
		fmt.Println("         2 登记收入")
		fmt.Println("         3 登记支出")
		fmt.Println("         4 退出")
		fmt.Println()
		fmt.Println("请选择(1-4):")
		fmt.Scanln(&this1.userKey) //接收用户输入参数

		switch this1.userKey {
		case "1":
			this1.showDetails()
		case "2":
			this1.income()
		case "3":
			this1.pay()
		case "4":
			this1.exit1()
		default:
			fmt.Println("输入有误,请重新输入...")
			this1.userKey = ""
		}
		if !this1.userexit { //判断userexit是否为假,如果为假则break退出for循环
			break
		}
	}
}

//将收支明细写成一个方法
func (this1 *FamilyAccount) showDetails() {
	fmt.Println("---------当前收支 明细记录---------")
	if this1.record {
		fmt.Println(this1.details)
	} else {
		fmt.Println("当前没有支出记录")
	}

	fmt.Println()
	this1.userKey = ""
}

//将登记收入写成一个方法
func (this1 *FamilyAccount) income() {
	//
	fmt.Println("登记收入金额:")
	fmt.Scanln(&this1.money)

	if this1.money == 0 {
		fmt.Println("输入金额有误,请重新输入...")
		return
	}
	value1 := true
	for i, v := range fmt.Sprintf("%.4f", this1.money) {

		if i == 0 && v == 46 {
			value1 = false
			break
		} else if v < 46 || v > 57 || v == 47 {
			value1 = false
			break
		}
	}
	if value1 {
		if len(fmt.Sprintf("%v", this1.money))-5 > 9 {
			fmt.Println("输入金额过大,你太有钱了。。")
			this1.userKey = ""
			//break
			return
		} else {
			this1.balance += this1.money //修改balance
			fmt.Println("收入情况说明:")
			fmt.Scanln(&this1.note)

			//将收入情况拼接到details变量
			this1.details += fmt.Sprintf("\n%-10s  %-15.4f  +%-15.4f  %-10s",
				"收入", this1.balance, this1.money, this1.note)

			this1.record = true
		}
	} else {
		fmt.Println("输入有误,请重新输入...")
		this1.userKey = ""
		//break
		return

	}
	//
	this1.userKey = ""
}

//登记支出
func (this1 *FamilyAccount) pay() {
	//
	fmt.Println("登记支出金额:")
	fmt.Scanln(&this1.money)
	if this1.money > this1.balance {
		fmt.Println("账户余额不足")
		//break //检测到余额不足时直接退出,后面将不再执行
		return
	}
	this1.balance -= this1.money
	fmt.Println("支出情况说明:")
	fmt.Scanln(&this1.note)

	//将收入情况拼接到details变量
	this1.details += fmt.Sprintf("\n%-10s  %-15.4f  -%-15.4f  %-10s",
		"收入", this1.balance, this1.money, this1.note)
	this1.record = true
	//
	this1.userKey = ""
}

//退出程序
func (this1 *FamilyAccount) exit1() {
	fmt.Println("真的要退出吗? y/n")
	yOrn := ""

	for {
		fmt.Scanln(&yOrn)
		if yOrn == "y" || yOrn == "n" {
			break
		}
		fmt.Println("输入有误,请输入 y/n")
	}
	if yOrn == "y" {
		this1.userexit = false //把userexet改为假false
		fmt.Println("正在退出...")
	} else {
		this1.userexit = true
	}

	this1.userKey = ""

}

main.go

package main

import (
	"demo2/01demo/02/utils" //引入utils包
	"fmt"
)

func main() {
	fmt.Println("这个是面向对象的方式完成。。。")
	utils.NewFamilyAccount().MainMeum() //创建utils的NewFamilyAccount的MainMeum
}




二、客户管理系统项目

1.项目需求分析

  1. 模拟实现基于文本界面的《客户信息管理软件》。
  2. 该软件能够实现对客户对象的插入、修改和删除(用切片实现),并能够打印客户明细表

2.项目的界面设计

  • 主菜单界面

    在这里插入图片描述

  • 添加客户界面

    在这里插入图片描述

  • 修改客户界面

    在这里插入图片描述

  • 删除客户界面

    在这里插入图片描述

  • 客户列表界面

    在这里插入图片描述

3.客户管理系统的程序框架图

在这里插入图片描述





3.项目功能实现

1)显示主菜单和完成退出

  • 功能的说明

    当用户运行程序时,可以看到主菜单,当输入5 时,可以退出该软件.

  • 思路分析

    编写customerView.go ,另外可以把customer.go 和customerService.go 写上.

  • 代码

    customerManage/model/customer.go

    package model
    
    //声明一个结构体表示客户信息
    type Customer struct {
    	Id     int
    	Name   string
    	Gender string
    	Age    int
    	Phone  string
    	Email  string
    }
    
    //使用工厂模式,返回Customer实例
    func NewCustomer(id int, name string, gender string, age int,
    	phone string, email string) Customer {
    	return Customer{
    		Id:     id,
    		Name:   name,
    		Gender: gender,
    		Age:    age,
    		Phone:  phone,
    		Email:  email,
    	}
    }
    

    customerManage/View/customerView.go

    package main
    
    import (
    	"fmt"
    )
    
    type CustomerView struct {
    	//定义必要的字段
    	userkey string //接收用户输入
    	loop    bool   //表示是否循环显示主菜单
    }
    
    //显示主菜单
    func (cv *CustomerView) MainMeum() {
    	for {
    		fmt.Println("------------客户信息管理系统------------")
    		fmt.Println("            ")
    		fmt.Println("            1 添加客户")
    		fmt.Println("            2 修改客户")
    		fmt.Println("            3 删除客户")
    		fmt.Println("            4 客户列表")
    		fmt.Println("            5 退    出")
    		fmt.Println("            ")
    		fmt.Println("请选择(1-5):")
    		fmt.Scanln(&cv.userkey)
    
    		switch cv.userkey {
    		case "1":
    			fmt.Println("------------添加客户------------")
    
    		case "2":
    			fmt.Println("------------修改客户------------")
    
    		case "3":
    			fmt.Println("------------删除客户------------")
    
    		case "4":
    			fmt.Println("------------客户列表------------")
    
    		case "5":
    			fmt.Println("------------退    出------------")
    		default:
    			fmt.Println("输入有误,请重新输入:")
    		}
    		if !cv.loop {
    			break
    		}
    	}
    	fmt.Println("你退出了客户管理系统")
    }
    
    func main() {
    	//在主函数中,创建一个customerView,并运行
    	customerView := CustomerView{
    		userkey: "",
    		loop:    true,
    	}
    
    	//显示主菜单
    	customerView.MainMeum()
    }
    




2)完成显示客户列表的功能

  • 功能说明

    在这里插入图片描述

  • 思路分析

    在这里插入图片描述

  • 代码

    customerManage/model/customer.go

    package model
    
    import "fmt"
    
    //声明一个结构体表示客户信息
    type Customer struct {
    	Id     int
    	Name   string
    	Gender string
    	Age    int
    	Phone  string
    	Email  string
    }
    
    //使用工厂模式,返回Customer实例
    func NewCustomer(id int, name string, gender string, age int,
    	phone string, email string) Customer {
    	return Customer{
    		Id:     id,
    		Name:   name,
    		Gender: gender,
    		Age:    age,
    		Phone:  phone,
    		Email:  email,
    	}
    }
    
    //获取用户信息,并返回
    func (gi Customer) Getinfo() string {
    	info := fmt.Sprintf("%-7v  %-9v  %-5v  %-6v  %-17v  %-15v\n",
    		gi.Id, gi.Name, gi.Gender, gi.Age, gi.Phone, gi.Email)
    	return info //返回info变量的字符串
    }
    

    customerManage/View/customerView.go

    package main
    
    import (
    	"demo2/03demo/customerManage/service"
    	"fmt"
    )
    
    type CustomerView struct {
    	//定义必要的字段
    	userkey         string                   //接收用户输入
    	loop            bool                     //表示是否循环显示主菜单
    	customerService *service.CustomerService //增加一个字段customerService ,需要引入包
    
    }
    
    //显示主菜单
    func (cv *CustomerView) MainMeum() {
    	for {
    		fmt.Println("------------客户信息管理系统------------")
    		fmt.Println("            ")
    		fmt.Println("            1 添加客户")
    		fmt.Println("            2 修改客户")
    		fmt.Println("            3 删除客户")
    		fmt.Println("            4 客户列表")
    		fmt.Println("            5 退    出")
    		fmt.Println("            ")
    		fmt.Println("请选择(1-5):")
    		fmt.Scanln(&cv.userkey)
    
    		switch cv.userkey {
    		case "1":
    			fmt.Println("----------------添加客户----------------")
    
    		case "2":
    			fmt.Println("----------------修改客户----------------")
    
    		case "3":
    			fmt.Println("----------------删除客户----------------")
    
    		case "4":
    			fmt.Println("----------------客户列表----------------")
    			cv.List()
    		case "5":
    			fmt.Println("----------------退    出----------------")
    		default:
    			fmt.Println("输入有误,请重新输入:")
    		}
    		if !cv.loop {
    			break
    		}
    	}
    	fmt.Println("你退出了客户管理系统")
    }
    
    //显示所有的客户信息
    func (cv *CustomerView) List() {
    	//首先,获取到当前所有的客户信息()
    	customer := cv.customerService.List()
    	fmt.Printf("%-5v  %-10v  %-4v  %-4v  %-15v  %-15v\n", "编号", "姓名", "性别", "年龄", "电话", "邮箱")
    	for i := 0; i < len(customer); i++ {
    		fmt.Println(customer[i].Getinfo()) //调用service.CustomerService下的Getinf函数并打印
    	}
    	fmt.Printf("--------------客户列表完成--------------\n\n\n")
    }
    
    func main() {
    	//在主函数中,创建一个customerView,并运行
    	customerView := CustomerView{
    		userkey: "",
    		loop:    true,
    	}
    	//这里完成对CustomerView结构体的Customerservice字段的初始化
    	customerView.customerService = service.NweCustomerService()
    
    	//显示主菜单
    	customerView.MainMeum()
    }
    

    customerManage/service/customerService.go

    package service
    
    import "demo2/03demo/customerManage/model"
    
    //使用CustomerService完成对Customer的操作,包括增删改查
    type CustomerService struct {
    	customers []model.Customer //把model包的Customer结构体使用切片的形式传入给当前结构体,并添加一个字段
    
    	//声明一个字段,表示当前切片含有多少个客户
    	//改字段后面,还可以作为新客户id+1
    	customerNum int
    }
    
    //编写一个方法,返回*CustomerService
    func NweCustomerService() *CustomerService {
    	//为了能够看到有客户在切片中,我们初始化一个客户
    	customerService := &CustomerService{} //声明CustomerService结构体
    
    	customerService.customerNum = 1 //给CustomerNum赋值
    
    	customer := model.NewCustomer(1, "管理员", "男", 0, "13000000000", "admin@123.com") //声明一个变量,传入一个默认客户信息
    
    	customerService.customers = append(customerService.customers, customer) //使用append自动扩容添加第一个客户
    
    	return customerService //返回customerService
    
    }
    
    //返回客户切片
    func (cs *CustomerService) List() []model.Customer {
    	return cs.customers //把CustomerService下的customers 返回给切片[]model.Customer
    }
    




3)添加客户的功能

  • 功能说明

    在这里插入图片描述

  • 思路分析

    在这里插入图片描述

  • 代码

    customerManage/model/customer.go

    package model
    
    import "fmt"
    
    //声明一个结构体表示客户信息
    type Customer struct {
    	Id     int
    	Name   string
    	Gender string
    	Age    string
    	Phone  string
    	Email  string
    }
    
    //使用工厂模式,返回Customer实例
    func NewCustomer(id int, name string, gender string, age string,
    	phone string, email string) Customer {
    	return Customer{
    		Id:     id,
    		Name:   name,
    		Gender: gender,
    		Age:    age,
    		Phone:  phone,
    		Email:  email,
    	}
    }
    
    //获取用户信息,并返回
    func (gi Customer) Getinfo() string {
    	info := fmt.Sprintf("%-7v  %-9v  %-5v  %-6v  %-17v  %-15v",
    		gi.Id, gi.Name, gi.Gender, gi.Age, gi.Phone, gi.Email)
    	return info //返回info变量的字符串
    }
    
    //第二种创建Customer实例方法, 不带id ,让系统自动分配
    func NewCustomer2(name string, gender string, age string,
    	phone string, email string) Customer {
    	return Customer{
    		Name:   name,
    		Gender: gender,
    		Age:    age,
    		Phone:  phone,
    		Email:  email,
    	}
    }
    

    customerManage/View/customerView.go

    package main
    
    import (
    	"demo2/03demo/customerManage/model"
    	"demo2/03demo/customerManage/service"
    	"fmt"
    )
    
    type CustomerView struct {
    	//定义必要的字段
    	userkey         string                   //接收用户输入
    	loop            bool                     //表示是否循环显示主菜单
    	customerService *service.CustomerService //增加一个字段customerService ,需要引入包
    
    }
    
    //显示主菜单
    func (cv *CustomerView) MainMeum() {
    	for {
    		fmt.Println("------------客户信息管理系统------------")
    		fmt.Println("            ")
    		fmt.Println("            1 添加客户")
    		fmt.Println("            2 修改客户")
    		fmt.Println("            3 删除客户")
    		fmt.Println("            4 客户列表")
    		fmt.Println("            5 退    出")
    		fmt.Println("            ")
    		fmt.Println("请选择(1-5):")
    		fmt.Scanln(&cv.userkey)
    
    		switch cv.userkey {
    		case "1":
    			fmt.Println("----------------添加客户----------------")
    			cv.Add()
    		case "2":
    			fmt.Println("----------------修改客户----------------")
    
    		case "3":
    			fmt.Println("----------------删除客户----------------")
    
    		case "4":
    			fmt.Println("----------------客户列表----------------")
    			cv.List()
    		case "5":
    			fmt.Println("----------------退    出----------------")
    			cv.loop = false
    		default:
    			fmt.Println("输入有误,请重新输入:")
    		}
    		if !cv.loop {
    			break
    		}
    	}
    	fmt.Println("你退出了客户管理系统")
    }
    
    //显示所有的客户信息
    func (cv *CustomerView) List() {
    	//首先,获取到当前所有的客户信息()
    	customer := cv.customerService.List()
    	fmt.Printf("%-5v  %-10v  %-4v  %-4v  %-15v  %-15v\n", "编号", "姓名", "性别", "年龄", "电话", "邮箱")
    	for i := 0; i < len(customer); i++ {
    		fmt.Println(customer[i].Getinfo()) //调用service.CustomerService下的Getinf函数并打印
    	}
    	fmt.Printf("--------------客户列表完成--------------\n\n\n")
    }
    
    //获取用户的输入,构建新的客户并添加
    func (cv CustomerView) Add() {
    	fmt.Println("姓名")
    	var userName string
    	fmt.Scanln(&userName)
    
    	fmt.Println("性别")
    	var userGender string
    	fmt.Scanln(&userGender)
    
    	fmt.Println("年龄")
    	var userAge string
    	fmt.Scanln(&userAge)
    
    	fmt.Println("电话")
    	var userPhone string
    	fmt.Scanln(&userPhone)
    
    	fmt.Println("邮箱")
    	var userEmail string
    	fmt.Scanln(&userEmail)
    
    	//id号是唯一的,需要系统分配
    	customer := model.NewCustomer2(userName, userGender, userAge, userPhone, userEmail) //调用model.NewCustomer2,引用model包
    
    	if cv.customerService.Add(customer) {
    		fmt.Println("----------------添加成功----------------")
    	} else {
    		fmt.Println("----------------添加失败----------------")
    	}
    
    }
    
    func main() {
    	//在主函数中,创建一个customerView,并运行
    	customerView := CustomerView{
    		userkey: "",
    		loop:    true,
    	}
    	//这里完成对CustomerView结构体的Customerservice字段的初始化
    	customerView.customerService = service.NweCustomerService()
    
    	//显示主菜单
    	customerView.MainMeum()
    }
    
    

    customerManage/service/customerService.go

    package service
    
    import "demo2/03demo/customerManage/model"
    
    //使用CustomerService完成对Customer的操作,包括增删改查
    type CustomerService struct {
    	customers []model.Customer //把model包的Customer结构体使用切片的形式传入给当前结构体,并添加一个字段
    
    	//声明一个字段,表示当前切片含有多少个客户
    	//改字段后面,还可以作为新客户id+1
    	customerNum int
    }
    
    //编写一个方法,返回*CustomerService
    func NweCustomerService() *CustomerService {
    	//为了能够看到有客户在切片中,我们初始化一个客户
    	customerService := &CustomerService{} //声明CustomerService结构体
    
    	customerService.customerNum = 1 //给CustomerNum赋值
    
    	customer := model.NewCustomer(1, "管理员", "男", "0", "13000000000", "admin@123.com") //声明一个变量,传入一个默认客户信息
    
    	customerService.customers = append(customerService.customers, customer) //使用append自动扩容添加第一个客户
    
    	return customerService //返回customerService
    
    }
    
    //返回客户切片
    func (cs *CustomerService) List() []model.Customer {
    	return cs.customers //把CustomerService下的customers 返回给切片[]model.Customer
    }
    
    //添加客户到customers切片
    func (cs *CustomerService) Add(custmoer model.Customer) bool {
    
    	cs.customerNum++             //让上面定的值自加,
    	custmoer.Id = cs.customerNum //并赋值给客户id
    	cs.customers = append(cs.customers, custmoer)
    	return true
    }
    




4)删除客户的功能

  • 功能说明

    在这里插入图片描述

  • 思路分析

    在这里插入图片描述

  • 代码

    customerManage/model/customer.go [没有变化]

    customerManage/service/customerService.go

    在这里插入图片描述

    customerManage/view/customerView.go

    在这里插入图片描述




5)退出确认功能

  • 功能说明:

    要求用户在退出时提示" 确认是否退出(Y/N):",用户必须输入y/n, 否则循环提示。

  • 思路分析:

    需要编写customerView.go

  • 代码

    在这里插入图片描述

    在这里插入图片描述




6)修改客户信息

在这里插入图片描述

4.完整代码

customerManage/model/customer.go

package model

import "fmt"

//声明一个结构体表示客户信息
type Customer struct {
	Id     int
	Name   string
	Gender string
	Age    string
	Phone  string
	Email  string
}

//使用工厂模式,返回Customer实例
func NewCustomer(id int, name string, gender string, age string,
	phone string, email string) Customer {
	return Customer{
		Id:     id,
		Name:   name,
		Gender: gender,
		Age:    age,
		Phone:  phone,
		Email:  email,
	}
}

//获取用户信息,并返回
func (gi Customer) Getinfo() string {
	info := fmt.Sprintf("%v\t%v\t%v\t%v\t%-11v\t%v",
		gi.Id, gi.Name, gi.Gender, gi.Age, gi.Phone, gi.Email)
	return info //返回info变量的字符串
}

//第二种创建Customer实例方法, 不带id ,让系统自动分配
func NewCustomer2(name string, gender string, age string,
	phone string, email string) Customer {
	return Customer{
		Name:   name,
		Gender: gender,
		Age:    age,
		Phone:  phone,
		Email:  email,
	}
}

customerManage/service/customerService.go

package service

import (
	"demo2/03demo/customerManage/model"
	"fmt"
)

//使用CustomerService完成对Customer的操作,包括增删改查
type CustomerService struct {
	customers []model.Customer //把model包的Customer结构体使用切片的形式传入给当前结构体,并添加一个字段

	//声明一个字段,表示当前切片含有多少个客户
	//改字段后面,还可以作为新客户id+1
	customerNum int
}

//编写一个方法,返回*CustomerService
func NweCustomerService() *CustomerService {
	//为了能够看到有客户在切片中,我们初始化一个客户
	customerService := &CustomerService{} //声明CustomerService结构体

	customerService.customerNum = 1 //给CustomerNum赋值

	customer := model.NewCustomer(1, "管理员", "男", "0", "13000000000", "admin@123.com") //声明一个变量,传入一个默认客户信息

	customerService.customers = append(customerService.customers, customer) //使用append自动扩容添加第一个客户

	return customerService //返回customerService

}

//返回客户切片
func (cs *CustomerService) List() []model.Customer {
	return cs.customers //把CustomerService下的customers 返回给切片[]model.Customer
}

//添加客户到customers切片
func (cs *CustomerService) Add(custmoer model.Customer) bool {

	cs.customerNum++             //让上面定的值自加,
	custmoer.Id = cs.customerNum //并赋值给客户id
	cs.customers = append(cs.customers, custmoer)
	return true
}

//删除客户-------------

//根据id查找客户在切片中对应下标,如果没有该客户, 返回-1
func (cs *CustomerService) FindById(id int) int {
	// fmt.Println(id)
	index := -1
	//遍历cs.customers 切片
	for i := 0; i < len(cs.customers); i++ {
		if cs.customers[i].Id == id {

			//找到了,就返回下标
			index = i
		}
	}
	return index
}

func (cs *CustomerService) Delete(id int) bool { //有没有删除成功返回一个bool
	index := cs.FindById(id)
	if index == -1 { //如果index == -1, 说明没有这个客户
		fmt.Println("没有找到此id")
		return false
	} else if index == 0 {
		fmt.Println("默认账号无法删除")
		return false
	}

	//如何从切片中删除一个元素
	//获取切片中index之前的所有数组,不包括index ,获取index之后的所有数组
	//然后使用append拼接,覆盖给CustomerService
	cs.customers = append(cs.customers[:index], cs.customers[index+1:]...)
	return true

}

//修改用户信息
//使用可以使用前面的查找
func (cs *CustomerService) Update(id int) bool {
	// fmt.Println("Update id =", id)
	index := cs.FindById(id)

	if index == -1 { //如果index == -1, 说明没有这个客户
		fmt.Println("没有找到此id")
		return false
	}

	fmt.Printf("请输入用户姓名(默认:%v): ", cs.customers[index].Name)
	var userName string
	fmt.Scanln(&userName)

	fmt.Printf("请输入用户性别(默认:%v): ", cs.customers[index].Gender)
	var userGender string
	fmt.Scanln(&userGender)

	fmt.Printf("请输入用户年龄(默认:%v): ", cs.customers[index].Age)
	var userAge string
	fmt.Scanln(&userAge)

	fmt.Printf("请输入用户电话(默认:%v): ", cs.customers[index].Phone)
	var userPhone string
	fmt.Scanln(&userPhone)

	fmt.Printf("请输入用户邮箱(默认:%v): ", cs.customers[index].Email)
	var userEmail string
	fmt.Scanln(&userEmail)

	if userName != "" {
		cs.customers[index].Name = userName
	}

	if userGender != "" {
		cs.customers[index].Gender = userGender
	}

	if userAge != "" {
		cs.customers[index].Age = userAge
	}

	if userPhone != "" {
		cs.customers[index].Phone = userPhone
	}
	if userEmail != "" {
		cs.customers[index].Email = userEmail
	}

	return true
}

//判断用户输入的是否为纯数字
func (cs *CustomerService) UserDigital(id string) bool {
	value1 := true
	for i, v := range id {
		if i == 0 && v == 46 {
			value1 = false
		} else if v < 46 || v > 57 {
			value1 = false
		}
	}
	if value1 {
		// fmt.Println("id是全部都是数字")
		return true
	} else {
		// fmt.Println("id不是完整的数字")
		return false
	}
}

customerManage/view/customerView.go

package main

import (
	"demo2/03demo/customerManage/model"
	"demo2/03demo/customerManage/service"
	"fmt"
	"strconv"
)

type CustomerView struct {
	//定义必要的字段
	userkey         string                   //接收用户输入
	loop            bool                     //表示是否循环显示主菜单
	customerService *service.CustomerService //增加一个字段customerService ,需要引入包

}

//显示主菜单
func (cv *CustomerView) MainMeum() {
	for {
		cv.userkey = ""
		fmt.Println("------------客户信息管理系统------------")
		fmt.Println("            ")
		fmt.Println("            1 添加客户")
		fmt.Println("            2 修改客户")
		fmt.Println("            3 删除客户")
		fmt.Println("            4 客户列表")
		fmt.Println("            5 退    出")
		fmt.Println("            ")
		fmt.Println("请选择(1-5):")
		fmt.Scanln(&cv.userkey)

		switch cv.userkey {
		case "1":
			fmt.Println("----------------添加客户----------------")
			cv.Add()

		case "2":
			fmt.Println("----------------修改客户----------------")
			cv.Update()
		case "3":
			fmt.Println("----------------删除客户----------------")
			cv.Delete()

		case "4":
			fmt.Println("----------------客户列表----------------")
			cv.List()

		case "5":
			fmt.Println("----------------退    出----------------")
			cv.Exit()

		default:
			fmt.Println("输入有误,请重新输入:")
		}
		if !cv.loop {
			break
		}
	}
	fmt.Println("你退出了客户管理系统")
}

//显示所有的客户信息
func (cv *CustomerView) List() {
	//首先,获取到当前所有的客户信息()
	customer := cv.customerService.List()
	fmt.Printf("%v\t%v\t%v\t%v\t%-11v\t%v\n", "编号", "姓名", "性别", "年龄", "电话", "邮箱")
	for i := 0; i < len(customer); i++ {
		fmt.Println(customer[i].Getinfo()) //调用service.CustomerService下的Getinf函数并打印
	}
	fmt.Printf("--------------客户列表完成--------------\n\n\n")
}

//获取用户的输入,构建新的客户并添加
func (cv CustomerView) Add() {
	fmt.Printf("姓名:")
	var userName string
	fmt.Scanln(&userName)

	fmt.Printf("性别:")
	var userGender string
	fmt.Scanln(&userGender)

	fmt.Printf("年龄:")
	var userAge string
	fmt.Scanln(&userAge)

	fmt.Printf("电话:")
	var userPhone string
	fmt.Scanln(&userPhone)

	fmt.Printf("邮箱:")
	var userEmail string
	fmt.Scanln(&userEmail)

	//id号是唯一的,需要系统分配
	customer := model.NewCustomer2(userName, userGender, userAge, userPhone, userEmail) //调用model.NewCustomer2,引用model包

	if cv.customerService.Add(customer) {
		fmt.Println("----------------添加成功----------------")
	} else {
		fmt.Println("----------------添加失败----------------")
	}

}

//得到用户输入id,删除该id对应的用户
func (cv *CustomerView) Delete() {
	fmt.Println("请删除id对应的用户")
	id := -1
	fmt.Scanln(&id)
	if id == -1 {
		return
	}

	for {
		fmt.Println("确认删除请输入(y/n)")
		choice := ""
		fmt.Scanln(&choice)

		exit := false
		if choice == "y" || choice == "Y" { //判断用户是否确定要删除
			exit = true
			//调用customerService的Delete方法,然后判断是否删除成功
			if cv.customerService.Delete(id) {
				fmt.Println("--------------用户删除成功--------------")
			} else {
				fmt.Println("--------------用户删除失败--------------")
			}
		} else if choice == "n" || choice == "N" {
			break
		} else {
			fmt.Println("---------输入有误,请重新输入---------")
		}
		if exit {
			break
		}
	}

}

//退出程序
func (cv *CustomerView) Exit() {
	for {
		fmt.Println("确认是否退出程序(y/n):")
		choice := ""
		fmt.Scanln(&choice)

		exit := true
		if choice == "y" || choice == "Y" || choice == "是" {
			fmt.Println("正在退出程序")
			cv.loop = false
			return
		} else if choice == "n" || choice == "N" || choice == "否" {
			return
		}
		if !exit {
			break
		}
	}
}

//修改客户信息
func (cv *CustomerView) Update() {
	fmt.Println("请输入id对应的用户")
	id := ""
	var idint int //用户把id修改为int类型

	switchloop := true

	for {
		fmt.Scanln(&id)

		if cv.customerService.UserDigital(id) {
			if id <= "0" {
				fmt.Println("输入的id有误,请重新输入:")

			} else {
				idint, _ = strconv.Atoi(id)
				if cv.customerService.Update(idint) {
					fmt.Println("修改成功")
					switchloop = false
				} else {
					fmt.Println("修改失败")
					switchloop = false
				}
			}
		} else {
			fmt.Println("输入的id有误,请重新输入")
			switchloop = false
		}
		if !switchloop {
			break
		}
	}
}

func main() {
	//在主函数中,创建一个customerView,并运行
	customerView := CustomerView{
		userkey: "",
		loop:    true,
	}
	//这里完成对CustomerView结构体的Customerservice字段的初始化
	customerView.customerService = service.NweCustomerService()

	//显示主菜单
	customerView.MainMeum()
}


章节目录

【Golang第1~3章:基础】如何安装golang、第一个GO程序、golang的基础

【Golang第4章:函数】Golang包的引用,return语句、指针、匿名函数、闭包、go函数参数传递方式,golang获取当前时间

【Golang第5章:数组与切片】golang如何使用数组、数组的遍历和、使用细节和内存中的布局;golang如何使用切片,切片在内存中的布局

【Golang第6章:排序和查找】golang怎么排序,golang的顺序查找和二分查找,go语言中顺序查找二分查找介绍和案例

【Golang第7章:map】go语言中map的基本介绍,golang中map的使用案例,go语言中map的增删改查操作,go语言对map的值进行排序

【Golang第8章:面向对象编程】Go语言的结构体是什么,怎么声明;Golang方法的调用和声明;go语言面向对象实例,go语言工厂模式;golang面向对象的三大特性:继承、封装、多态

【Golang第9章:项目练习】go项目练习家庭收支记账软件项目、go项目练习客户管理系统项目

【Golang第10章:文件操作】GO语言的文件管理,go语言读文件和写文件、GO语言拷贝文件、GO语言判断文件是否存在、GO语言Json文件格式和解析

【Golang第11章:单元测试】GO语言单元测试

【Golang第12章:goroutine协程与channel管道】GO语言goroutine协程和channel管道的基本介绍、goroutine协

posted @ 2022-12-14 17:12  雪花凌落的盛夏  阅读(25)  评论(0编辑  收藏  举报  来源