一峰说:学习Golang之旅

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

Golang文档:https://studygolang.com/pkgdoc

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中国 https://studygolang.com/dl
一般都是下载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 = 300
	n4 = 900
	name2 = "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 main

import (
	"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 main

import "fmt"

var totalLevel int = 9

func 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 main

import (
	"fmt"
)

type Cat struct {
	Name string
	Age int 
	Color string
}

func main() {

	var cat1 Cat
	cat1.Name = "小白"
	cat1.Age = 20
	cat1.Color = "白色"
	fmt.Println("猫猫的信息如下:")
	fmt.Println("name=", cat1.Name)
	fmt.Println("Age=",cat1.Age)
	fmt.Println("Color=", cat1.Color)

}

在这里插入图片描述

19.接口编程的案例

package main

import (
	"fmt"
	"sort"
	"math/rand"
)

//1.声明Hero结构体
type Hero struct{
	Name string
	Age 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 HeroSlice
	for 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.Sort
	sort.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 := ""
	//声明一个变量,控制是否推出for
	loop := 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 = false
			default :
				fmt.Println("请输入正确的选项..")
			}

			if !loop {
				break
			}
	
	}

	fmt.Println("你退出家庭记账软件的使用")
}

功能2完成可以显示明细和登记收入的功能
思路分析:
1)因为需要显示明细,我们定义一个变量details string来记录
2)还需要定义变量来记录余额,每次收支的金额,每次收支的说明
走代码

package main
import (
	"fmt"
)

func main() {
	//声明一个变量,保存接受用户输入的选项
	key := ""
	//声明一个变量,控制是否推出for
	loop := 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 = false
			default :
				fmt.Println("请输入正确的选项..")
			}

			if !loop {
				break
			}
	
	}

	fmt.Println("你退出家庭记账软件的使用")
}

在这里插入图片描述

功能3完成登记支出的功能
思路分析:
登记支出的功能和登记收入的功能类似,做一些修改即可
走代码

package main
import (
	"fmt"
)

func main() {
	//声明一个变量,保存接受用户输入的选项
	key := ""
	//声明一个变量,控制是否推出for
	loop := 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 -= money
				fmt.Println("本次支出说明:")
				fmt.Scanln(&note)
				details += fmt.Sprintf("\n收入\t%v\t\t%v\t\t%v", balance, money, note)
			case "4":
				loop = false
			default :
				fmt.Println("请输入正确的选项..")
			}

			if !loop {
				break
			}
	
	}

	fmt.Println("你退出家庭记账软件的使用")
}

在这里插入图片描述
项目改进,用户输入4退出时,给出提示,必须输入正确的y/n,否则循环输入指令,直到输入y或者n

package main
import (
	"fmt"
)

func main() {
	//声明一个变量,保存接受用户输入的选项
	key := ""
	//声明一个变量,控制是否推出for
	loop := 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 -= money
				fmt.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 = true

			case "3":
				fmt.Println("本次支出金额:")
				fmt.Scanln(&money)
				//这里需要做一个必要的判断
				if money > balance {
					fmt.Println("余额的金额不足")
					break
				}
				balance -= money
				fmt.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 main

import (
	"project02/familyaccount/utils"
	"fmt"
	
	
)

func main() {
	fmt.Println("这个是面向对象的方式完成~~")
	utils.NewFamilyAccount().MainMenu()
}



FamilyAccount.go

package utils

import (
	"fmt"
)

type FamilyAccount struct {
	//声明一个变量,保存接受用户输入的选项
	key string
	//声明一个变量,控制是否推出for
	loop 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.money
	fmt.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
		}
	}
}

注意:导包的时候要注意路径问题
https://blog.csdn.net/aaaaaab_/article/details/99690341

21.客户信息管理系统

显示主菜单和退出软件功能

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

//model层:
package model

//声明一个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,
	}
}
//service层
package service
import (
	"project02/customerManage/model"
)


//该CustomerService,完成对Customer的操作,包括
//增删查改
type CustomerService struct {

	customers []model.Customer
	//声明一个字段,表示当前切片含有多少个客户
	//该字段后面,还可以作为新客户的id+1
	customerNum int
}
//view层
package main

import (
	"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 = false
			default : 
				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 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 (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+1
	customerNum int
}

//编写一个方法,可以返回 CustomerService
func NewCustomerService() *CustomerService{
	//为了能够看到有客户在切片中,我们初始化一个客户
	customerService := &CustomerService{}
	customerService.customerNum = 1
	customer := model.NewCustomer(1, "张三", "男", 20, "112", "yf@sohu.com")
	customerService.customers = append(customerService.customers, customer)
	return customerService
}

//返回客户切片
func (this *CustomerService) List() []model.Customer{
	return this.customers
}
//view
package main

import (
	"fmt"
	"project02/customerManage/service"
)

type customerView struct {
	
	//定义必要字段
	key string //接受用户输入...
	loop bool	//表示是否循环的显示主菜单
	//增加一个字段customerService
	customerService *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 = false
			default : 
				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 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的实例
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+1
	customerNum int
}

//编写一个方法,可以返回 CustomerService
func NewCustomerService() *CustomerService{
	//为了能够看到有客户在切片中,我们初始化一个客户
	customerService := &CustomerService{}
	customerService.customerNum = 1
	customer := model.NewCustomer(1, "张三", "男", 20, "112", "yf@sohu.com")
	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.customerNum
	this.customers = append(this.customers, customer)
	return true
}
//view层
package main

import (
	"fmt"
	"project02/customerManage/service"
	"project02/customerManage/model"
)

type customerView struct {
	
	//定义必要字段
	key string //接受用户输入...
	loop bool	//表示是否循环的显示主菜单
	//增加一个字段customerService
	customerService *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 := 0
	fmt.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 = false
			default : 
				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 := -1
	fmt.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
		}
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一峰说

坚持价值输出

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值