一峰说:学习Golang之旅

编程入门 行业动态 更新时间:2024-10-24 00:30:45

一峰说:学习Golang<a href=https://www.elefans.com/category/jswz/34/1770100.html style=之旅"/>

一峰说:学习Golang之旅

以下是本人学习的观点,如果有错或者说得不全面,记得告诉我哟

Golang文档:

1.Golang学习方向

1.区块链研发工程师
2.Go服务器端=》数据处理,处理大并发 、游戏软件工程师
3.Golang分布式/云计算、软件工程师

这些都离不开Golang核心编程

2.Golang的应用领域

  1. 区块链技术,简称BT
  2. 后端服务器应用(美团后台流量支撑程序)
  3. 云计算/云服务后台应用(盛大云CDN即内容分发网络)

3.Golang的学习方法

  • 高效愉快学
  • 先建立一个整体框架,再细化
  • 在实际工作的时候,要培养边学边用的能力
  • 先知道怎么做,再知道为什么
  • 不是会了再做,而是做了才会
  • 学习琢磨别人怎么做,而不是自己认为怎么做
  • 先学原理和基本语法,来个快速入门再去理解细节

4.Google为什么要创造Go语言

  1. 计算机不能合理利用资源
  2. 现在的编程语言,风格不统一,计算能力不够,处理大并发不够好
  3. 有些编程语言有内存泄露的问题,例如c/c++

5.Golang的特点

Go=C+python C静态语言程序速度和python动态语言的快速开发

  1. C语言中继承很多理念,包括表达式语法,控制结构,指针等
  2. 引入包的概念,用于组织程序结构,Go语言的每个文件都属于一个包
  3. 垃圾自动回收机制
  4. 天然并发,有轻量级的线程
  5. 吸收了管道通信机制
  6. 函数可以返回多个值
  7. 增加了切片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程序开发的注意事项

  1. “go”为扩展名
  2. 入口是main()函数
  3. 严格区分大小写
  4. 每个语句后面不需要加分号,加也可以,不过没有必要
  5. 一行写一条语句
  6. 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的整型使用细节

  1. Golang各整数类型分:有符号和无符号,int uint的大小和系统有关。
  2. Golang的整型默认声明为int型
  3. 如何在程序查看某个变量的字节大小和数据类型(使用较多)
var n2 int64 = 10
fmt.Printf("n2 的类型 %T n2占用的字节数是 %d", n2, unsafe.Sizeof(n1))
  1. Golang程序中整型变量在使用时,遵守保小不保大的原则,在程序正常运行下,尽量使用占用空间小的数据类型
  2. bit:计算机中的最小存储单位,byte:计算机中基本存储单元。

12.Golang的浮点类型使用细节

  1. Golang浮点类型有固定的范围和字段长度。不受具体OS的影响
  2. Golang的浮点型默认声明为float64类型
  3. 浮点型常量有两种表示形式:十进制数形式:如5.12 .512(必须有小数点) 科学计数法形式:5.1234e2=5.12*10的2次方
  4. 通常情况下,应该使用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)
}
  1. 字符常量是单引号括起来的,例如 ‘a’
  2. Go中允许使用转义字符’'来将其后的字符转变为特殊字符型常量 '\n’表示换行符
  3. Go语言的字符使用utf-8
  4. Go中字符的本质是一个整数,直接输出是该字符对应的utf-8编码的码值
  5. 可以直接给出某个变量赋上一个数字,然后按格式化输出%c,输出该数字对应的unicode字符
  6. 字符类型是可以进行运算的,相当于一个整数,因为它都对应有unicode码

14.Golang布尔类型注意事项

  1. bool类型占用存储空间是1个字节
  2. bool类型只能取true或者false

15.Golang的字符串类型细节

  1. Go语言的字符串的字节使用utf-8编码标识Unicode文本
  2. 字符串一旦赋了值,字符串就不能修改了,在Go中字符串是不可变的
  3. 字符串的两种表示形式:(1)双引号,会识别转义字符(2)反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击,输出源代码等效果

16.Golang基本数据类型的转换

  1. Go中数据类型的转换可以是从范围小->范围大,也可以逆转
  2. 被转换的是变量存储的值,不是数据类型
  3. 在转换的时候,int64转换成int8,编译时不会报错,只是结果可能会被溢出处理
  4. 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面向对象编程

  1. Golang并不是纯粹的面向对象语言,它支持面向对象编程特性是比较准确的。
  2. Golang没有类,是基于struct来实现OOP特性的
  3. Golang面向对象编程非常简洁,去掉了传统的OOP语言的集成,方法重载,构造函数和析构函数,隐藏的this指针等等。
  4. Golang仍然有面向对象的特性,例如继承,Golang没有extends关键字,继承是通过匿名字段来实现
  5. 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. 项目采用分级菜单方式,主菜单如下:
    家庭收支记账软件:
    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(&note)//将这个收入情况,拼接到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(&note)//将这个收入情况,拼接到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(&note)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(&note)//将这个收入情况,拼接到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(&note)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(&note)//将这个收入情况,拼接到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(&note)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之旅

本文发布于:2024-03-07 04:47:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1716883.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:之旅   一峰说   Golang

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!