学习一门语言最好的方式就是通过一个实际的例子。通过这个实例,不仅可以进一步巩固golang的相关基础技能,同时,也能让我们加强自己的逻辑能力,从一步步的调用函数,掌握参数传递和接收技巧。
项目2 - 客户信息关系系统
该项目很好的展示了基于面向对象的增删改查功能的实现。
任何一个项目在敲代码之前都要做好需求分析
项目需求分析
-
模拟实现基于文本界面的《客户信息管理软件》
-
该软件能够实现对客户对象的插入,修改和删除(用切片实现),并能够打印客户明细表
项目总体架构
代码区
customer.go
package model
import "fmt"
//声明一个Customer结构体,表示一个客户的必要信息
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,
}
}
//第二种创建Customer实例方法,不带id
func NewCustomer2(name string, gender string, age int, phone string, email string) Customer {
return Customer{
Name: name,
Gender: gender,
Age: age,
Phone: phone,
Email: email,
}
}
//返回用户的信息,格式化的字符串
func (cm Customer) GetInfo() string {
info := fmt.Sprintf("%v %v %v %v %v %v ", cm.Id, cm.Name, cm.Gender, cm.Age, cm.Phone, cm.Email)
return info
}
customerService.go
package service
import "2020-04-08/customerManage/model"
//该CustomerService 完成对Customer的操作,包括增删改查
type CustomerService struct {
customers []model.Customer
//声明一个字段,表示当前切片含有多少个客户
//该字段后面,还可以作为新客户的id + 1
customerId int
}
//编写一个方法,可以返回*CustomerService
func NewCustomerService() *CustomerService {
//为了能够看到有客户在切片中,初始化一个客户
customerService := &CustomerService{}
customerService.customerId = 1
customer := model.NewCustomer(1, "紫色飞猪","男",22,"00000000000","zisefeizhu@qq.com")
customerService.customers = append(customerService.customers, customer)
return customerService
}
//返回客列表切片
func (cs *CustomerService) List() []model.Customer {
return cs.customers
}
//添加客户到customers切片
func (cs *CustomerService) Add(customer model.Customer) bool {
//确定一个分配id的规则,就是添加的顺序
cs.customerId++
customer.Id = cs.customerId
cs.customers = append(cs.customers, customer)
return true
}
//根据id查找客户在切片对应下标,如果没有该客户,返回-1
func (cs *CustomerService) FindById(id int) int {
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 {
index := cs.FindById(id)
//如果index == -1, 说明没有这个客户
if index == -1 {
return false
}
//如何从切片中删除一个元素
cs.customers = append(cs.customers[:index], cs.customers[index+1:]...)
return true
}
func (cs *CustomerService) GetInfoById(id int) model.Customer {
i := id - 1
return cs.customers[i]
}
//根据id修改客户信息
func (cs *CustomerService) Update(id int, customer model.Customer) bool {
for i := 0; i < len(cs.customers); i++ {
if cs.customers[i].Id == id {
cs.customers[i].Name = customer.Name
cs.customers[i].Gender = customer.Gender
cs.customers[i].Age = customer.Age
cs.customers[i].Phone = customer.Phone
cs.customers[i].Email = customer.Email
}
}
return true
}
customerView.go
package main
import (
"2020-04-08/customerManage/model"
"2020-04-08/customerManage/service"
"fmt"
)
type customerView struct {
//定义必要字段
key string //接受用户输入
loop bool //表示是否循环的显示主菜单
customerService *service.CustomerService
}
//显示所有的客户信息
func (cv *customerView) list() {
//首先,获取到当前的客户信息(在切片中)
customers := cv.customerService.List()
//显示
fmt.Println("------------------客户列表------------------")
fmt.Println("编号 姓名 性别 年龄 电话 邮箱")
for i := 0; i < len(customers); i++ {
fmt.Println(customers[i].GetInfo())
}
fmt.Println("------------------客户列表------------------")
}
//得到用户的输入信息构成新的客户,并完成添加
func (cv *customerView) add() {
fmt.Println("------------------添加客户------------------")
fmt.Print("姓名:")
name := ""
fmt.Scanln(&name)
fmt.Print("性别:")
gender := ""
fmt.Scanln(&gender)
fmt.Print("年龄:")
age := 0
fmt.Scanln(&age)
fmt.Print("电话:")
phone := ""
fmt.Scanln(&phone)
fmt.Print("电邮:")
email := ""
fmt.Scanln(&email)
//构建一个新的Customer实例
//注意id号,没有让用户输入,id是唯一的,需要系统分配
customer := model.NewCustomer2(name, gender, age, phone, email)
//调用
if cv.customerService.Add(customer) {
fmt.Println("------------------添加完成------------------")
} else {
fmt.Println("------------------添加失败------------------")
}
}
//得到用户的输入id,删除该id对应的客户
func (cv *customerView) delete() {
fmt.Println("------------------删除客户------------------")
fmt.Print("请选择等待删除客户编号(-1退出):")
id := -1
fmt.Scanln(&id)
if id == -1 {
return //放弃删除操作
}
fmt.Print("确认是否删除(Y/N):")
//这里可以加入一个循环判断,直到用户输入y或者n,才退出...
choice := ""
fmt.Scanln(&choice)
if choice == "y" || choice == "Y" {
//调用customerService的Delete方法
if cv.customerService.Delete(id) {
fmt.Println("------------------删除完成------------------")
} else {
fmt.Println("------------------删除失败,输入的id号不存在")
}
}
}
//得到用户的输入id,修改该id对应的客户
func (cv *customerView) update() {
cv.list()
fmt.Println()
fmt.Println("------------------修改客户------------------")
fmt.Print("请选择等待修改客户编号(-1退出):")
id := -1
fmt.Scanln(&id)
if id == -1 {
return //放弃删除操作
}
fmt.Print("确认是否修改(Y/N):")
//这里可以加入一个循环判断,直到用户输入y或者n,才退出...
choice := ""
fmt.Scanln(&choice)
if choice == "y" || choice == "Y" {
//调用customerService的Delete方法
if cv.customerService.FindById(id) != -1 {
customer := cv.customerService.GetInfoById(id)
fmt.Printf("姓名(%v:)", customer.Name)
name := ""
fmt.Scanln(&name)
fmt.Printf("性别(%v):", customer.Gender)
gender := ""
fmt.Scanln(&gender)
fmt.Printf("年龄(%v):", customer.Age)
age := 0
fmt.Scanln(&age)
fmt.Printf("电话(%v):", customer.Phone)
phone := ""
fmt.Scanln(&phone)
fmt.Printf("邮箱(%v):", customer.Email)
email := ""
fmt.Scanln(&email)
customer2 := model.NewCustomer2(name, gender, age, phone, email)
cv.customerService.Update(id, customer2)
fmt.Println("------------------修改完成------------------")
} else {
fmt.Println("------------------修改失败,输入的id号不存在")
}
}
}
//退出
func (cv *customerView) logout() {
fmt.Print("确认是否退出(Y/N):")
for {
fmt.Scanln(&cv.key)
if cv.key == "Y" || cv.key =="y" || cv.key =="N" || cv.key =="n" {
break
}
fmt.Print("你的输入有误,确认是否退出(Y/N): ")
}
if cv.key == "Y" || cv.key == "y" {
cv.loop = false
}
}
//显示主菜单
func (cv *customerView) mainMenu() {
for {
fmt.Println("------------------客户信息管理软件------------------")
fmt.Println(" 1 添加客户")
fmt.Println(" 2 修改客户")
fmt.Println(" 3 删除客户")
fmt.Println(" 4 客户列表")
fmt.Println(" 5 退 出")
//fmt.Println("请选择(1 - 5):") 换行
fmt.Print("请选择(1 - 5):")
fmt.Scanln(&cv.key)
switch cv.key {
case "1":
//fmt.Println("添 加 客 户")
cv.add()
case "2":
//fmt.Println("修 改 客 户")
cv.update()
case "3":
cv.delete()
case "4":
//fmt.Println("客 户 列 表")
cv.list()
case "5":
//cv.loop = false
cv.logout()
default:
fmt.Print("你的输入有误,请重新输入...")
}
if !cv.loop {
break
}
}
fmt.Println("你已经退出了客户关系系统...")
}
func main() {
//在main函数中,创建一个customerView,并运行显示主菜单
customerView := customerView{
key: "",
loop: true,
}
//完成对customerView结构体的customerService字段的初始化
customerView.customerService = service.NewCustomerService()
//显示主菜单
customerView.mainMenu()
}
验证
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):4
------------------客户列表------------------
编号 姓名 性别 年龄 电话 邮箱
1 紫色飞猪 男 22 00000000000 zisefeizhu@qq.com
------------------客户列表------------------
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):1
------------------添加客户------------------
姓名:jingxing
性别:女
年龄:21
电话:00000000000
电邮:jingxing@qq.com
------------------添加完成------------------
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):2
------------------客户列表------------------
编号 姓名 性别 年龄 电话 邮箱
1 紫色飞猪 男 22 00000000000 zisefeizhu@qq.com
2 jingxing 女 21 00000000000 jingxing@qq.com
------------------客户列表------------------
------------------修改客户------------------
请选择等待修改客户编号(-1退出):2
确认是否修改(Y/N):n
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):2
------------------客户列表------------------
编号 姓名 性别 年龄 电话 邮箱
1 紫色飞猪 男 22 00000000000 zisefeizhu@qq.com
2 jingxing 女 21 00000000000 jingxing@qq.com
------------------客户列表------------------
------------------修改客户------------------
请选择等待修改客户编号(-1退出):2
确认是否修改(Y/N):y
姓名(jingxing:)jingxing
性别(女):女
年龄(21):22
电话(00000000000):00000000000
邮箱(jingxing@qq.com):jingxing@qq.com
------------------修改完成------------------
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):4
------------------客户列表------------------
编号 姓名 性别 年龄 电话 邮箱
1 紫色飞猪 男 22 00000000000 zisefeizhu@qq.com
2 jingxing 女 22 00000000000 jingxing@qq.com
------------------客户列表------------------
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):3
------------------删除客户------------------
请选择等待删除客户编号(-1退出):-1
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):3
------------------删除客户------------------
请选择等待删除客户编号(-1退出):2
确认是否删除(Y/N):n
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):3
------------------删除客户------------------
请选择等待删除客户编号(-1退出):2
确认是否删除(Y/N):y
------------------删除完成------------------
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):4
------------------客户列表------------------
编号 姓名 性别 年龄 电话 邮箱
1 紫色飞猪 男 22 00000000000 zisefeizhu@qq.com
------------------客户列表------------------
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):5
确认是否退出(Y/N):n
------------------客户信息管理软件------------------
1 添加客户
2 修改客户
3 删除客户
4 客户列表
5 退 出
请选择(1 - 5):5
确认是否退出(Y/N):y
你已经退出了客户关系系统...
总结
此项目带给我的最重要意义是:什么时候需要* 什么时候不需要*
当需要修改结构体的变量内容的时候,方法传入的结构体变量参数需要使用指针,也就是结构体的地址。需要修改map中的架构体的变量的时候也需要使用结构体地址作为map的value。如果仅仅是读取结构体变量,可以不使用指针,直接传递引用即可。*type 这里的type这个变量存放的东西是地址,这点需要明确,需要使用&type获取到地址。