之旅"/>
一峰说:学习Golang之旅
以下是本人学习的观点,如果有错或者说得不全面,记得告诉我哟
Golang文档:
1.Golang学习方向
1.区块链研发工程师
2.Go服务器端=》数据处理,处理大并发 、游戏软件工程师
3.Golang分布式/云计算、软件工程师
这些都离不开Golang核心编程
2.Golang的应用领域
- 区块链技术,简称BT
- 后端服务器应用(美团后台流量支撑程序)
- 云计算/云服务后台应用(盛大云CDN即内容分发网络)
3.Golang的学习方法
- 高效愉快学
- 先建立一个整体框架,再细化
- 在实际工作的时候,要培养边学边用的能力
- 先知道怎么做,再知道为什么
- 不是会了再做,而是做了才会
- 学习琢磨别人怎么做,而不是自己认为怎么做
- 先学原理和基本语法,来个快速入门再去理解细节
4.Google为什么要创造Go语言
- 计算机不能合理利用资源
- 现在的编程语言,风格不统一,计算能力不够,处理大并发不够好
- 有些编程语言有内存泄露的问题,例如c/c++
5.Golang的特点
Go=C+python C静态语言程序速度和python动态语言的快速开发
- C语言中继承很多理念,包括表达式语法,控制结构,指针等
- 引入包的概念,用于组织程序结构,Go语言的每个文件都属于一个包
- 垃圾自动回收机制
- 天然并发,有轻量级的线程
- 吸收了管道通信机制
- 函数可以返回多个值
- 增加了切片slice,延时执行defer等
6.在windows下搭建Go开发环境
安装和配置SDK
SDK下载地址:Golang中国
一般都是下载zip的,可以解压后直接使用
要配置环境变量,分别是
GOROOT:指定是SDK的安装路径 ……/go
Path:添加SDK的/bin目录 %GOROOT%\bin
GOPATH:工作目录,将来我们的go项目的工作路径
7.Go的目录
- go文件的后缀是.go
- package main表示hello.go文件所在包是main
- 编译:go build hello.go生成exe文件
- 用go run test.go可以直接运行,但是实际工作的时候是先编译再运行
8.Go程序开发的注意事项
- “go”为扩展名
- 入口是main()函数
- 严格区分大小写
- 每个语句后面不需要加分号,加也可以,不过没有必要
- 一行写一条语句
- import的包没用到,就不能通过编译
9.Golang的变量使用方式
1.指定变量类型,声明后若不赋值,使用默认值
var i int
fmt.Println("i=",i)
2.根据值自行判断变量类型
var num = 10.11
fmt.Println("num=",num)
3.类型推导。省略var,用 :=,等价于var name string name ="tom"
name := "tom"
fmt.Println("name", name)
4.全局一次性声明变量
var (n3 = 300n4 = 900name2 = "fanny"
)
5.该区域的数据值可以在同一类型范围内不断变化
6.变量在同一作用域内不能重名
7.变量=变量名+值+数据类型
8.Golang的变量如果没有赋值,编译器会使用默认值,比如int默认值为0,string的默认值为空
10.Go的数据类型
11.Golang的整型使用细节
- Golang各整数类型分:有符号和无符号,int uint的大小和系统有关。
- Golang的整型默认声明为int型
- 如何在程序查看某个变量的字节大小和数据类型(使用较多)
var n2 int64 = 10
fmt.Printf("n2 的类型 %T n2占用的字节数是 %d", n2, unsafe.Sizeof(n1))
- Golang程序中整型变量在使用时,遵守保小不保大的原则,在程序正常运行下,尽量使用占用空间小的数据类型
- bit:计算机中的最小存储单位,byte:计算机中基本存储单元。
12.Golang的浮点类型使用细节
- Golang浮点类型有固定的范围和字段长度。不受具体OS的影响
- Golang的浮点型默认声明为float64类型
- 浮点型常量有两种表示形式:十进制数形式:如5.12 .512(必须有小数点) 科学计数法形式:5.1234e2=5.12*10的2次方
- 通常情况下,应该使用float64,因为它比float32更精准
13.Golang的字符串注意事项
package mainimport ("fmt"
)func main(){var c1 byte = 'a'var c2 byte = '0'fmt.Println("c1=",c1)fmt.Println("c2=",c2)fmt.Printf("c1=%c c2=%c\n", c1, c2)var c3 int = '北'fmt.Printf("c3=%c c3对应码值=%d", c3, c3)
}
- 字符常量是单引号括起来的,例如 ‘a’
- Go中允许使用转义字符’'来将其后的字符转变为特殊字符型常量 '\n’表示换行符
- Go语言的字符使用utf-8
- Go中字符的本质是一个整数,直接输出是该字符对应的utf-8编码的码值
- 可以直接给出某个变量赋上一个数字,然后按格式化输出%c,输出该数字对应的unicode字符
- 字符类型是可以进行运算的,相当于一个整数,因为它都对应有unicode码
14.Golang布尔类型注意事项
- bool类型占用存储空间是1个字节
- bool类型只能取true或者false
15.Golang的字符串类型细节
- Go语言的字符串的字节使用utf-8编码标识Unicode文本
- 字符串一旦赋了值,字符串就不能修改了,在Go中字符串是不可变的
- 字符串的两种表示形式:(1)双引号,会识别转义字符(2)反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击,输出源代码等效果
16.Golang基本数据类型的转换
- Go中数据类型的转换可以是从范围小->范围大,也可以逆转
- 被转换的是变量存储的值,不是数据类型
- 在转换的时候,int64转换成int8,编译时不会报错,只是结果可能会被溢出处理
- Golang如果数据类型转换失败,例如将“hello”转换为整数,则会它直接转成0
17.指针
1.获取变量的地址
2.指针变量存的是一个地址,这个地址指向的空间存的才是值
3.获取指针类型所指向的值
*fmt.Printf(“ptr 指向的值=%v”, ptr)
16.空心三角形
package mainimport "fmt"var totalLevel int = 9func main(){//用for循环完成下面的案例编写一个程序,可以接受以一个整数for i := 1; i <=totalLevel; i++ {for k := 1; k <= totalLevel - i;k++ {fmt.Print(" ")}for j :=1; j <= 2 * i - 1; j++ {if j == 1 || j == 2 * i - 1 || i == totalLevel {fmt.Print("*")}else {fmt.Print(" ")}}fmt.Println()}
}
17.Golang面向对象编程
- Golang并不是纯粹的面向对象语言,它支持面向对象编程特性是比较准确的。
- Golang没有类,是基于struct来实现OOP特性的
- Golang面向对象编程非常简洁,去掉了传统的OOP语言的集成,方法重载,构造函数和析构函数,隐藏的this指针等等。
- Golang仍然有面向对象的特性,例如继承,Golang没有extends关键字,继承是通过匿名字段来实现
- GOlang中面向接口编程是非常重要的特性
18.结构体
来搞一只小猫猫
package mainimport ("fmt"
)type Cat struct {Name stringAge int Color string
}func main() {var cat1 Catcat1.Name = "小白"cat1.Age = 20cat1.Color = "白色"fmt.Println("猫猫的信息如下:")fmt.Println("name=", cat1.Name)fmt.Println("Age=",cat1.Age)fmt.Println("Color=", cat1.Color)}
19.接口编程的案例
package mainimport ("fmt""sort""math/rand"
)//1.声明Hero结构体
type Hero struct{Name stringAge int Score float64
}//2.声明一个Hero结构体切片类型
type HeroSlice []Hero//3.实现Interface接口
func (hs HeroSlice) Len() int {return len(hs)
}//Less方法就是决定你使用什么标准进行排序
//1.按Hero的年龄从小到大排序
func (hs HeroSlice) Less(i, j int) bool {return hs[i].Age < hs[j].Age}func (hs HeroSlice) Swap(i, j int) {// temp := hs[i]// hs[i] = hs[j]// hs[j] = temp//上面三句话等价于这句话hs[i], hs[j] = hs[j], hs[i]
}func main() {//先定义一个数组/切片var intSlice = []int{0,-1,10,7,90}//要求对intSlice切片进行排序//1.冒泡排序//2.也可以使用提供的方法sort.Ints(intSlice)fmt.Println(intSlice)//请大家对结构体切片进行排序//1.冒泡排序//2.也可以使用提供的方法//测试看看我们是否可以对结构体切片进行排序var heroes HeroSlicefor i := 0; i < 10 ; i++ {hero := Hero{Name : fmt.Sprintf("英雄~%d", rand.Intn(100)),Age : rand.Intn(100),}//将 hero append 到heroes切片heroes = append(heroes, hero)}//看看排序前的顺序for _ , v := range heroes {fmt.Println(v)}//调用sort.Sortsort.Sort(heroes)fmt.Println("排序后------------------")//看看排序后的顺序for _ , v := range heroes {fmt.Println(v)}}
20.家庭收支记账项目
项目介绍
功能:
- 模拟实现基于文本界面的《家庭记账软件》
- 该软件能够记录家庭的收入,支出,并能够打印收支明细表
- 项目采用分级菜单方式,主菜单如下:
家庭收支记账软件:
1.收支明细
2.登记收入
3.登记支出
4.退出
请选择(1-4):_
基本功能
功能1先完成可以显示主菜单,并且可以退出
思路分析:
更加给出的界面完成,主菜单的,当用户输入4时,就退出该程序
走代码
package main
import ("fmt"
)func main() {//声明一个变量,保存接受用户输入的选项key := ""//声明一个变量,控制是否推出forloop := true//显示这个主菜单for {fmt.Println("----------家庭收支记账软件----------------")fmt.Println(" 1 收支明细")fmt.Println(" 2 登记收入")fmt.Println(" 3 登记支出")fmt.Println(" 4 退出软件")fmt.Print("请选择(1-4): ")fmt.Scanln(&key)switch key {case "1":fmt.Println("----------当前收支明细记录----------------")case "2":case "3":fmt.Println("登记支出..")case "4":loop = falsedefault :fmt.Println("请输入正确的选项..")}if !loop {break}}fmt.Println("你退出家庭记账软件的使用")
}
功能2完成可以显示明细和登记收入的功能
思路分析:
1)因为需要显示明细,我们定义一个变量details string来记录
2)还需要定义变量来记录余额,每次收支的金额,每次收支的说明
走代码
package main
import ("fmt"
)func main() {//声明一个变量,保存接受用户输入的选项key := ""//声明一个变量,控制是否推出forloop := 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)switch key {case "1":fmt.Println("----------当前收支明细记录----------------")fmt.Println(details)case "2":fmt.Println("本次收入金额:")fmt.Scanln(&money)balance += money //修改账户余额fmt.Println("本次收入说明:")fmt.Scanln(¬e)//将这个收入情况,拼接到details变量//收入 11000 1000 有人发红包details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", balance, money, note)case "3":fmt.Println("登记支出..")case "4":loop = falsedefault :fmt.Println("请输入正确的选项..")}if !loop {break}}fmt.Println("你退出家庭记账软件的使用")
}
功能3完成登记支出的功能
思路分析:
登记支出的功能和登记收入的功能类似,做一些修改即可
走代码
package main
import ("fmt"
)func main() {//声明一个变量,保存接受用户输入的选项key := ""//声明一个变量,控制是否推出forloop := 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)switch key {case "1":fmt.Println("----------当前收支明细记录----------------")fmt.Println(details)case "2":fmt.Println("本次收入金额:")fmt.Scanln(&money)balance += money //修改账户余额fmt.Println("本次收入说明:")fmt.Scanln(¬e)//将这个收入情况,拼接到details变量//收入 11000 1000 有人发红包details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", balance, money, note)case "3":fmt.Println("本次支出金额:")fmt.Scanln(&money)//这里需要做一个必要的判断if money > balance {fmt.Println("余额的金额不足")break}balance -= moneyfmt.Println("本次支出说明:")fmt.Scanln(¬e)details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", balance, money, note)case "4":loop = falsedefault :fmt.Println("请输入正确的选项..")}if !loop {break}}fmt.Println("你退出家庭记账软件的使用")
}
项目改进,用户输入4退出时,给出提示,必须输入正确的y/n,否则循环输入指令,直到输入y或者n
package main
import ("fmt"
)func main() {//声明一个变量,保存接受用户输入的选项key := ""//声明一个变量,控制是否推出forloop := 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)switch key {case "1":fmt.Println("----------当前收支明细记录----------------")fmt.Println(details)case "2":fmt.Println("本次收入金额:")fmt.Scanln(&money)balance += money //修改账户余额fmt.Println("本次收入说明:")fmt.Scanln(¬e)//将这个收入情况,拼接到details变量//收入 11000 1000 有人发红包details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", balance, money, note)case "3":fmt.Println("本次支出金额:")fmt.Scanln(&money)//这里需要做一个必要的判断if money > balance {fmt.Println("余额的金额不足")break}balance -= moneyfmt.Println("本次支出说明:")fmt.Scanln(¬e)details += fmt.Sprintf("\n收入\t%v\t\t%v\t\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" {loop = false}default :fmt.Println("请输入正确的选项..")}if !loop {break}}fmt.Println("你退出家庭记账软件的使用")
}
当前没有收支明细
fmt.Scanln(&key)switch key {case "1":fmt.Println("----------当前收支明细记录----------------")if flag {fmt.Println(details)} else {fmt.Println("当前没有收支明细...来一笔吧!")}case "2":fmt.Println("本次收入金额:")fmt.Scanln(&money)balance += money //修改账户余额fmt.Println("本次收入说明:")fmt.Scanln(¬e)//将这个收入情况,拼接到details变量//收入 11000 1000 有人发红包details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", balance, money, note)flag = truecase "3":fmt.Println("本次支出金额:")fmt.Scanln(&money)//这里需要做一个必要的判断if money > balance {fmt.Println("余额的金额不足")break}balance -= moneyfmt.Println("本次支出说明:")fmt.Scanln(¬e)details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", balance, money, note)flag = true
将面向过程的代码改成面向对象的方法
思路分析:
把记账软件的功能,封装到一个结构体中,然后调用该结构体的方法,来实现记账,显示明细。
在通过main方法中,创建一个结构体实例,实现记账即可
代码实现:不需要重写,需要重新组织一下
** mian.go**
package mainimport ("project02/familyaccount/utils""fmt")func main() {fmt.Println("这个是面向对象的方式完成~~")utils.NewFamilyAccount().MainMenu()
}
FamilyAccount.go
package utilsimport ("fmt"
)type FamilyAccount struct {//声明一个变量,保存接受用户输入的选项key string//声明一个变量,控制是否推出forloop bool//定义账户的余额balance float64//每次收支的金额money float64//每次收支的说明note string//定义个变量,记录是否有收支的行为flag bool//收支的详情使用字符串来记录//当有收支时,只需要对details进行拼接details string
}//编写要给工厂模式的构造方法,返回一个*FamilyAccount实例
func NewFamilyAccount()* FamilyAccount {return &FamilyAccount{key : "",loop : true,balance : 10000.0,money : 0.0,note : "",flag : false,}
}//将显示明细写成一个方法
func (this *FamilyAccount) showDetails() {fmt.Println("----------当前收支明细记录----------------")if this.flag {fmt.Println(this.details)} else {fmt.Println("当前没有收支明细...来一笔吧!")}
}//将登记收入写成一个犯法,和*FamilyAccount绑定
func (this *FamilyAccount) income() {fmt.Println("本次收入金额:")fmt.Scanln(&this.money)this.balance += this.money //修改账户余额fmt.Println("本次收入说明:")fmt.Scanln(&this.note)//将这个收入情况,拼接到details变量//收入 11000 1000 有人发红包this.details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", this.balance, this.money, this.note)this.flag = true
}//将登记支出成一个犯法,和*FamilyAccount绑定
func (this *FamilyAccount) pay() {fmt.Println("本次支出金额:")fmt.Scanln(&this.money)//这里需要做一个必要的判断if this.money > this.balance {fmt.Println("余额的金额不足")// break}this.balance -= this.moneyfmt.Println("本次支出说明:")fmt.Scanln(&this.note)this.details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", this.balance, this.money, this.note)this.flag = true
}//将退出系统写成一个方法
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.loop = false}
}//给该结构体绑定相应的方法
//显示主菜单
func (this *FamilyAccount) MainMenu() {//显示这个主菜单for {fmt.Println("\n----------家庭收支记账软件----------------")fmt.Println(" 1 收支明细")fmt.Println(" 2 登记收入")fmt.Println(" 3 登记支出")fmt.Println(" 4 退出软件")fmt.Print("请选择(1-4): ")fmt.Scanln(&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.loop {break}}
}
注意:导包的时候要注意路径问题
21.客户信息管理系统
显示主菜单和退出软件功能
当用户运行程序时,可以看到主菜单,当输入5时,可以退出该软件
//model层:
package model//声明一个Customer结构体,表示一个客户信息type Customer struct {Id intName stringGender stringAge intPhone stringEmail 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,}
}
//service层
package service
import ("project02/customerManage/model"
)//该CustomerService,完成对Customer的操作,包括
//增删查改
type CustomerService struct {customers []model.Customer//声明一个字段,表示当前切片含有多少个客户//该字段后面,还可以作为新客户的id+1customerNum int
}
//view层
package mainimport ("fmt"
)type customerView struct {//定义必要字段key string //接受用户输入...loop bool //表示是否循环的显示主菜单
}//显示主菜单
func (this *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.Scanln(&this.key)switch this.key {case "1" :fmt.Println("添 加 客 户")case "2" :fmt.Println("修 改 客 户")case "3" :fmt.Println("删 除 客 户")case "4" :fmt.Println("客 户 列 表")case "5" :this.loop = falsedefault : fmt.Println("你的输入有误,请重新输入...")}if !this.loop {break}}fmt.Println("你退出了客户关系管理系统...")
}func main(){//在main函数中,创建一个customerView,并运行显示主菜单customerView := customerView{key : "",loop : true,}//显示主菜单customerView.mainMenu()
}
显示客户列表的功能
修改后的每个模块
//model层
package model
import("fmt"
)//声明一个Customer结构体,表示一个客户信息type Customer struct {Id intName stringGender stringAge intPhone stringEmail 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 (this Customer) GetInfo() string {info := fmt.Sprintf("%v\t%v\t%v\t%v\t%v\t%v\t",this.Id,this.Name,this.Gender,this.Age,this.Phone,this.Email)return info
}
//service
package service
import ("project02/customerManage/model"
)//该CustomerService,完成对Customer的操作,包括
//增删查改
type CustomerService struct {customers []model.Customer//声明一个字段,表示当前切片含有多少个客户//该字段后面,还可以作为新客户的id+1customerNum int
}//编写一个方法,可以返回 CustomerService
func NewCustomerService() *CustomerService{//为了能够看到有客户在切片中,我们初始化一个客户customerService := &CustomerService{}customerService.customerNum = 1customer := model.NewCustomer(1, "张三", "男", 20, "112", "yf@sohu")customerService.customers = append(customerService.customers, customer)return customerService
}//返回客户切片
func (this *CustomerService) List() []model.Customer{return this.customers
}
//view
package mainimport ("fmt""project02/customerManage/service"
)type customerView struct {//定义必要字段key string //接受用户输入...loop bool //表示是否循环的显示主菜单//增加一个字段customerServicecustomerService *service.CustomerService
}//显示所有客户信息
func (this *customerView) list() {//首先,获取到当前所有的客户信息(在切片中)customers := this.customerService.List()//显示fmt.Println("--------------------客户列表--------------------")fmt.Println("编号\t姓名\t性别\t年龄\t电话\t邮箱")for i := 0; i < len(customers); i++{fmt.Println(customers[i].GetInfo())}fmt.Printf("\n--------------------客户列表完成----------------\n\n")
}//显示主菜单
func (this *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.Scanln(&this.key)switch this.key {case "1" :fmt.Println("添 加 客 户")case "2" :fmt.Println("修 改 客 户")case "3" :fmt.Println("删 除 客 户")case "4" :this.list()case "5" :this.loop = falsedefault : fmt.Println("你的输入有误,请重新输入...")}if !this.loop {break}}fmt.Println("你退出了客户关系管理系统...")
}func main(){//在main函数中,创建一个customerView,并运行显示主菜单customerView := customerView{key : "",loop : true,}//这里完成对customerView结构体的customerService字段的初始化customerView.customerService = service.NewCustomerService()//显示主菜单customerView.mainMenu()
}
添加客户的功能
改动过的代码:
//model层
package model
import("fmt"
)//声明一个Customer结构体,表示一个客户信息type Customer struct {Id intName stringGender stringAge intPhone stringEmail 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的实例
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 (this Customer) GetInfo() string {info := fmt.Sprintf("%v\t%v\t%v\t%v\t%v\t%v\t",this.Id,this.Name,this.Gender,this.Age,this.Phone,this.Email)return info
}
//service层
package service
import ("project02/customerManage/model"
)//该CustomerService,完成对Customer的操作,包括
//增删查改
type CustomerService struct {customers []model.Customer//声明一个字段,表示当前切片含有多少个客户//该字段后面,还可以作为新客户的id+1customerNum int
}//编写一个方法,可以返回 CustomerService
func NewCustomerService() *CustomerService{//为了能够看到有客户在切片中,我们初始化一个客户customerService := &CustomerService{}customerService.customerNum = 1customer := model.NewCustomer(1, "张三", "男", 20, "112", "yf@sohu")customerService.customers = append(customerService.customers, customer)return customerService
}//返回客户切片
func (this *CustomerService) List() []model.Customer{return this.customers
}//添加客户到customers切片
func (this *CustomerService) Add(customer model.Customer) bool{//我们确定一个分配id的规则,就是添加的顺序this.customerNum++customer.Id = this.customerNumthis.customers = append(this.customers, customer)return true
}
//view层
package mainimport ("fmt""project02/customerManage/service""project02/customerManage/model"
)type customerView struct {//定义必要字段key string //接受用户输入...loop bool //表示是否循环的显示主菜单//增加一个字段customerServicecustomerService *service.CustomerService
}//显示所有客户信息
func (this *customerView) list() {//首先,获取到当前所有的客户信息(在切片中)customers := this.customerService.List()//显示fmt.Println("--------------------客户列表--------------------")fmt.Println("编号\t姓名\t性别\t年龄\t电话\t邮箱")for i := 0; i < len(customers); i++{fmt.Println(customers[i].GetInfo())}fmt.Printf("\n--------------------客户列表完成----------------\n\n")
}//得到用户的输入,信息构建新的客户,并完成添加
func (this *customerView) add(){fmt.Println("--------------------添加客户--------------------")fmt.Println("姓名:")name := ""fmt.Scanln(&name)fmt.Println("性别:")gender := ""fmt.Scanln(&gender)fmt.Println("年龄:")age := 0fmt.Scanln(&age)fmt.Println("电话:")phone := ""fmt.Scanln(&phone)fmt.Println("电邮:")email := ""fmt.Scanln(&email)//构建一个新的Customer实例//注意id号,没有让用户输入,id是唯一的,应该让系统自动分配customer := model.NewCustomer2(name, gender, age, phone, email)//调用if this.customerService.Add(customer){fmt.Println("--------------------添加成功--------------------")}else{fmt.Println("--------------------添加失败--------------------")}
}//显示主菜单
func (this *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.Scanln(&this.key)switch this.key {case "1" :this.add()case "2" :fmt.Println("修 改 客 户")case "3" :fmt.Println("删 除 客 户")case "4" :this.list()case "5" :this.loop = falsedefault : fmt.Println("你的输入有误,请重新输入...")}if !this.loop {break}}fmt.Println("你退出了客户关系管理系统...")
}func main(){//在main函数中,创建一个customerView,并运行显示主菜单customerView := customerView{key : "",loop : true,}//这里完成对customerView结构体的customerService字段的初始化customerView.customerService = service.NewCustomerService()//显示主菜单customerView.mainMenu()
}
删除客户的功能
只增加了两个方法
//service
//根据id查找客户在切片中对应下标,如果没有该客户,返回-1
func (this *CustomerService) FindById(id int) int{index := -1//遍历this.customer 切片for i := 0; i < len(this.customers); i++{if this.customers[i].Id == id {//找到index = i}}return index
}
//view层
//得到用户的输入id,删除该id对应的客户
func (this *customerView) delete() {fmt.Println("--------------------删除客户--------------------")fmt.Println("请选择待删除客户编号(-1退出):")id := -1fmt.Scanln(&id)if id == -1 {return //放弃删除操作}fmt.Println("确认是否删除(Y/N):")choice := ""fmt.Scanln(&choice)if choice == "y" || choice == "Y" {//调用customerService 的Delete方法if this.customerService.Delete(id){fmt.Println("--------------------删除完成--------------------")}else {fmt.Println("--------------------删除失败:输入的id号不存在---")}}
}
完善退出确认功能
增加了一些代码
//view层
//退出软件
func (this *customerView) exit() {fmt.Println("确认是否退出(Y/N): ")for {fmt.Scanln(&this.key)if this.key == "Y" || this.key == "y" || this.key == "N" || this.key == "n" {break}fmt.Println("你的输入有误,确认是否退出(Y/N):")}if this.key == "Y" || this.key == "y" {this.loop = false}
}
更多推荐
一峰说:学习Golang之旅
发布评论