Golang&&学习笔记1

Golang&&学习笔记1

参考资料:

  1. Golang标准库文档
  2. Go 编程语言 - 包

变量

声明变量的三种方式

在这里插入图片描述
一次性声明多个变量。
在这里插入图片描述
声明全局变量。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

变量的数据类型

在这里插入图片描述
基本数据类型

整数型

  • int:
  • int8: (长度为)8位(范围内的有符号)整数类型。2^7 = 128,故可表示的整数范围在 -128 ~ 127 。
  • int32: rune 为 int32 的别名。
  • uint8: byte 为 uint8 的别名。(长度为)8位(范围内的无符号)整数类型。可表示的整数范围在 0 ~ 255 。

8位 等于 1字节

在这里插入图片描述

var i = 100
// 如何查看变量的数据类型
// fmt.Printf() 常用于做格式化输出。
fmt.Printf("变量i的数据类型是 %T\n", i)

// 如何查看变量的字节大小
fmt.Printf("变量i占用的字节数是 %d", unsafe.Sizeof(i))

浮点类型

在这里插入图片描述

浮点数都是有符号的。
float64 的精度比 float32 的要准确。开发中,推荐使用 float64 !
浮点型 默认声明为 float64 类型。

在这里插入图片描述

字符型

使用byte来保存单个字母字符。
一个汉字字符占3个byte。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

布尔型

bool 类型占1个字节。

字符串型

字符串 是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。

Go的字符串,是由字节组成的。
Go语言的字符串的字节使用UTF-8编码标识Unicode文本。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

%v,表示按照变量的原始值输出。

基本数据类型(位大小)的转换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基本数据类型和string的转换

基本数据类型转string

方式一:Sprintf 根据于格式说明符进行格式化并返回其结果字符串。
在这里插入图片描述
方式二:strconv 函数
在这里插入图片描述
方式三:Itoa是FormatInt(i, 10) 的简写。可以很方便的把int转为string。
在这里插入图片描述

string转基本数据类型

在这里插入图片描述

在接收函数的返回结果时,如果对多余的返回值不关心,可以使用下划线 “_” 接受多余的值。

在这里插入图片描述
在这里插入图片描述

在类型转换中,如果类型不匹配(如字符串型转整数型),则将直接转成默认值(如0,false等)。

指针

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

值类型和引用类型

在这里插入图片描述
在这里插入图片描述

标识符

  1. xxxxx
  2. 下划线 “_” 本身在Go中是一个特殊的标识符,称为 空标识符。可以代表任何其他的标识符,但是它对应的值会被忽略(比如 忽略某个返回值)。所以仅能被作为占位符使用,不能作为标识符使用。

在这里插入图片描述

运算符

算术运算符

算术运算符是对 数值类型的变量 进行运算的。如:加减乘除。

在这里插入图片描述

关系运算符

在这里插入图片描述
在这里插入图片描述

逻辑运算符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

赋值运算符

在这里插入图片描述
在这里插入图片描述

位运算符

在这里插入图片描述

其他运算符

在这里插入图片描述
在这里插入图片描述

获取用户终端输入

在这里插入图片描述
在这里插入图片描述

流程控制

switch 分支控制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

for 循环控制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

对于 for-range 遍历方式而言,是按照字符方式遍历,因此如果字符串中包含中文,也完全没问题。

while 和 do…while 的实现

在这里插入图片描述

跳转控制语句 - break

package main

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

func main() {
	for {
		// 在go中,我们为了生成一个随机数,需要为rand设置一个种子,否则返回的值总是固定的。
		// time.Now().Unix(): 返回一个从 1970-1-1 0:0:0 到现在的一个秒数
		// rand.Seed(time.Now().Unix())
		// time.Now().UnixNano(): 返回一个从 1970-1-1 0:0:0 到现在的纳秒数
		rand.Seed(time.Now().UnixNano())
		var randNum int = rand.Intn(100) + 1
		fmt.Println("randNum=", randNum)
		if randNum == 99 {
			break
		}
	}
}

break 语句用于终止某个语句块的执行,用于中断当前 for 循环或跳出 switch 语句。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

跳转控制语句 - continue

在这里插入图片描述
在这里插入图片描述

跳转控制语句 - goto

在这里插入图片描述

跳转控制语句 - return

在这里插入图片描述
在这里插入图片描述

函数

在这里插入图片描述

函数-递归调用

一个函数在函数体内又调用了本身,我们称为递归调用。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

函数注意事项和细节讨论

在这里插入图片描述

函数重载:即函数名相同,而形参的个数或数据类型不同的现象。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

slice: 切片

在这里插入图片描述

init函数

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

匿名函数

在这里插入图片描述
在这里插入图片描述

  1. “包”,为了更好的管理一组相关性强的功能集合,引入了包的概念。如fmt(格式化IO)等。
  2. 通常创建一个名字为包名的文件夹,其内有多个子文件,子文件的首行通常为 “package 包名”。
  3. 包的本质 实际上就是创建不同的文件夹,来存放程序文件
  4. go的每一个文件都是属于一个包的,也就是说,go是以包的形式来管理文件和项目目录结构的。

包的三大作用

在这里插入图片描述

package main

import (
    // 如果想保留一个没有实际使用到的包,可以通过在前面加下划线 "_" 表示忽略该包。
	_ "fmt"
)

如何引入自己的包

  1. 找到go的工作目录(即为配置的GOPATH路径)。
  2. 进入src目录,从src内的目录开始写引入包的路径。

在这里插入图片描述

包使用 注意事项和细节

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

库文件utils.a ,随编译生成,无法直接阅读,常用作SDK,配合接口文档使用。

在这里插入图片描述
在这里插入图片描述

闭包

基本介绍
闭包就是一个函数和与其相关的引用环境结合的一个整体(实体)。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

defer

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

函数参数传递方式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

变量的作用域

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

常见函数

字符串函数

在这里插入图片描述

builtin: 内建函数,可直接使用而不需要引入包。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

时间和日期函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
统计函数执行时间
在这里插入图片描述

内置函数(buildin)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Go 错误处理机制

在这里插入图片描述

使用 defer + recover 来处理错误异常

package main

import (
	"fmt"
)

func testPanic() {
	defer func() {
		err := recover() // recover()内置函数,可以捕获到异常
		if err != nil {  // 说明捕获到错误
			fmt.Println("err=", err)
		}
	}()
	num1 := 10
	num2 := 0
	res := num1 / num2
	fmt.Println("res= ", res)
}
func main() {
	testPanic()
	fmt.Println("testPanic()函数执行完毕!")
}

自定义错误

在这里插入图片描述

package main

import (
	"errors"
	"fmt"
)

func readConf(name string) (err error) {
	if name == "config.ini" {
		return nil
	} else {
		// 返回一个自定义错误
		return errors.New("读取文件异常。。。")
	}
}

func testPanic() {
	err := readConf("config.ini1")
	if err != nil {
		panic(err)
	}
	fmt.Println("testPanic()函数执行至最后一行!")
}
func main() {
	testPanic()
	fmt.Println("testPanic()函数执行完毕!")
}

数组

数组可以存放多个同一类型数据。
数组也是一种数据类型,在Go中,数组是值类型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

fmt.Printf %p,即point,常用于打印地址。

数组的使用

访问数组元素

在这里插入图片描述
四种初始化数组的方式
在这里插入图片描述
在这里插入图片描述

数组 使用注意事项和细节

在这里插入图片描述

[3]int,在go语言中,3被认为是数组的一部分。因此,[3]int,[4]int属于两种数据类型。

在这里插入图片描述
(8)
在这里插入图片描述
(9)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

切片

在这里插入图片描述
在这里插入图片描述

切片在内存中的形式

在这里插入图片描述

在这里插入图片描述

使用切片的三种方式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

切片的使用

在这里插入图片描述

切片的遍历

在这里插入图片描述

切片的注意事项和细节

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

string 和 slice 的使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数组排序

冒泡排序

顺序查找

二分查找

多维数据-二维数据

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

map

map 是 key-value数据结构,又称为字段或者关联数组。类似其他编程语言的集合

map 的声明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
## map使用的方式
在这里插入图片描述
在这里插入图片描述

map 使用的课堂案例

在这里插入图片描述

map 的增删改查操作

在这里插入图片描述

map 删除

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

map 查找

在这里插入图片描述
在这里插入图片描述

map 的遍历

在这里插入图片描述
在这里插入图片描述

map 切片

在这里插入图片描述
在这里插入图片描述

map 排序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

map 使用细节

在这里插入图片描述
在这里插入图片描述

结构体

go 语言中,对象 = 结构体 = struct

go 语言中没有类class的概念。

Golang 语言面向对象编程说明
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

结构体变量(实例)在内存中的布局

在这里插入图片描述

结构体 struct 是值类型

字段/属性

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建结构体实例的四种方式

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

日常开发中,推荐使用 方式2。
在这里插入图片描述
在这里插入图片描述
示例: struct类型的内存分配机制
在这里插入图片描述

在这里插入图片描述

结构体使用细节

  1. 结构体的所有字段在内存中是连续的。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

p 是值拷贝,改变 p 的值不会影响到变量(示例)的属性的值。可以通过传递地址实现对变量(示例)属性值的修改。

  1. p 的名字,由程序员指定,不是固定的。建议使用结构体名字的小写代替。 func (person Person) test() { }

方法的调用和传参机制原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法 注意事项和细节讨论

在这里插入图片描述
2.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.
在这里插入图片描述
5.
在这里插入图片描述
在这里插入图片描述

方法和函数的区别

在这里插入图片描述
在这里插入图片描述

结构体 方法的传递方式是值拷贝还是地址引用,取决于方法编写时取的是什么,不取决于结构体变量传的是值还是指针。

在这里插入图片描述

底层编译器做了优化处理

在这里插入图片描述
在这里插入图片描述

创建结构体变量时 指定字段值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

工厂模式

在这里插入图片描述
在这里插入图片描述
工厂模式示例
在这里插入图片描述
在这里插入图片描述
一个结构体的字段是私有的,该如何去访问?

在这里插入图片描述

在这里插入图片描述

VSCode 的使用

设置

在这里插入图片描述

快捷键

在这里插入图片描述

面向对象编程的三大特性

在这里插入图片描述

封装

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

继承

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

深入讨论

在这里插入图片描述
在这里插入图片描述

继承 不是将多层的结构体混为单一平面,而是保存多层结构体嵌套顺序。
故,在寻找变量时,如果在当前层级找不到目标变量,将重复向上层寻找。
故,在更新变量时,如果更新了当前层级的目标变量,上层级的同名变量值不改变。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

多重继承

在这里插入图片描述

接口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

应用场景

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

注意事项和细节

在这里插入图片描述
(1) / (4)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
即我们可以把任何一个变量赋给空接口。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

接口最佳实践

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

接口和继承的比较

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现接口 是对 继承机制 的补充。

在这里插入图片描述

接口不负责具体的实现(只制定规范),当需要执行方法时,直接使用其他数据类型写好的具体方法即可。
比如我 要 吃 这个功能,具体怎么实现吃这个动作,我不管,我只告诉你吃是什么效果,只要你能满足我要的效果,当我 要 吃 的时候,我就可以执行你的方法达到吃的效果。

多态

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

类型断言

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

类型断言的最佳实践

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

家庭收支记账软件项目

项目开发流程

在这里插入图片描述

需求说明

在这里插入图片描述

设计阶段

在这里插入图片描述

实现阶段

在这里插入图片描述
在这里插入图片描述

package main

import (
	"fmt"
)

func main() {
	// 保存用户输入的选项
	var choiceNum int
	// 控制是否退出for
	var ifLogout bool = false
	// 保存账户余额
	var balance float64 = 10000.0
	// 每次收支金额
	var money float64 = 0.0
	// 每次收支的说明
	var note string = ""
	// 收支详细信息
	var detail string = "收支\t账户金额\t收支金额\t说    明\n"
	// 是否确定退出
	var ifConfirm string = ""

	for {
		fmt.Println("------------------家庭收支记账软件------------------")
		fmt.Println()
		fmt.Println("                    1 收支明细")
		fmt.Println("                    2 登记收入")
		fmt.Println("                    3 登记支出")
		fmt.Println("                    4 退    出")
		fmt.Println()
		fmt.Print("                    请选择(1-4):")
		fmt.Scanln(&choiceNum)
		fmt.Println()

		switch choiceNum {
		case 1:
			fmt.Println("------------------当前收支明细记录------------------")
			fmt.Println(detail)
		case 2:
			fmt.Print("本次收入金额:")
			fmt.Scanln(&money)
			// 修改账户余额
			balance = balance + money
			fmt.Print("本次收入说明:")
			fmt.Scanln(&note)
			// 记录收支明细
			detail += fmt.Sprintf("收入\t%v\t\t%v\t\t%v\n", balance, money, note)
		case 3:
			fmt.Print("本次支出金额:")
			fmt.Scanln(&money)
			if money > balance {
				fmt.Println("您的余额不足!")
				break
			}
			// 修改账户余额
			balance -= money
			fmt.Print("本次支出说明:")
			fmt.Scanln(&note)
			// 记录收支明细
			detail += fmt.Sprintf("支出\t%v\t\t%v\t\t%v\n", balance, money, note)
		case 4:
			for {
				fmt.Print("你确定要退出吗? y/n:")
				fmt.Scanln(&ifConfirm)
				if ifConfirm == "y" {
					ifLogout = true
					break
				}
				if ifConfirm == "n" {
					break
				}
				fmt.Println("请输入y/n")

			}

		default:
			fmt.Println("请输入正确的选项。")
		}
		if ifLogout {
			break
		}
	}

	fmt.Println(choiceNum)
	fmt.Println("您已登出软件。")

}

变更为面向对象编程

在这里插入图片描述

main.go

package main

import (
	"fmt"
	"homeBill/utils"
)

func main() {

	utils.NewFamilyAccount().MainMenu()
	fmt.Println("您已登出软件。")

}

familyAccount.go

package utils

import (
	"fmt"
)

type FamilyAccount struct {
	ChoiceNum   int
	IfLogout    bool
	IfHasDetail bool
	Balance     float64
	Money       float64
	Note        string
	Detail      string
}

func NewFamilyAccount() *FamilyAccount {
	return &FamilyAccount{
		// 保存用户输入的选项
		ChoiceNum: 0,
		// 控制是否退出for
		IfLogout:    false,
		IfHasDetail: false,
		// 保存账户余额
		Balance: 10000.0,
		// 每次收支金额
		Money: 0.0,
		// 每次收支的说明
		Note: "",
		// 收支详细信息
		Detail: "收支\t账户金额\t收支金额\t说    明\n",
	}

}

// 显示明细
func (familyAccount *FamilyAccount) showDetails() {
	if familyAccount.IfHasDetail {
		fmt.Println("------------------当前收支明细记录------------------")
		fmt.Println(familyAccount.Detail)
	} else {
		fmt.Println("当前没有任何收支明细。")
	}

}

// 登记收入
func (familyAccount *FamilyAccount) inCome() {
	fmt.Print("本次收入金额:")
	fmt.Scanln(&(familyAccount.Money))
	// 修改账户余额
	familyAccount.Balance += familyAccount.Money
	fmt.Print("本次收入说明:")
	fmt.Scanln(&(familyAccount.Note))
	// 记录收支明细
	familyAccount.Detail += fmt.Sprintf("收入\t%v\t\t%v\t\t%v\n", familyAccount.Balance, familyAccount.Money, familyAccount.Note)
	familyAccount.IfHasDetail = true
}

// 登记支出
func (familyAccount *FamilyAccount) pay() {
	fmt.Print("本次支出金额:")
	fmt.Scanln(&(familyAccount.Money))
	if familyAccount.Money > familyAccount.Balance {
		fmt.Println("您的余额不足!")
		return
	}
	// 修改账户余额
	familyAccount.Balance -= familyAccount.Money
	fmt.Print("本次支出说明:")
	fmt.Scanln(&(familyAccount.Note))
	// 记录收支明细
	familyAccount.Detail += fmt.Sprintf("支出\t%v\t\t%v\t\t%v\n", familyAccount.Balance, familyAccount.Money, familyAccount.Note)
	familyAccount.IfHasDetail = true
}

// 退出软件
func (familyAccount *FamilyAccount) exit() {
	// 是否确定退出
	var ifConfirm string = ""
	fmt.Print("你确定要退出吗? y/n:")
	for {
		fmt.Scanln(&ifConfirm)
		if ifConfirm == "y" {
			familyAccount.IfLogout = true
			break
		}
		if ifConfirm == "n" {
			break
		}
		fmt.Println("请输入y/n")
	}
}

// 显示主菜单
func (familyAccount *FamilyAccount) MainMenu() {
	for {
		fmt.Println("------------------家庭收支记账软件------------------")
		fmt.Println()
		fmt.Println("                    1 收支明细")
		fmt.Println("                    2 登记收入")
		fmt.Println("                    3 登记支出")
		fmt.Println("                    4 退    出")
		fmt.Println()
		fmt.Print("                    请选择(1-4):")
		fmt.Scanln(&(familyAccount.ChoiceNum))
		fmt.Println()

		switch familyAccount.ChoiceNum {
		case 1:
			familyAccount.showDetails()
		case 2:
			familyAccount.inCome()
		case 3:
			familyAccount.pay()
		case 4:
			familyAccount.exit()
		default:
			fmt.Println("请输入正确的选项。")
		}
		if familyAccount.IfLogout {
			break
		}
	}
}

客户关系管理项目

需求说明

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

设计阶段

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
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,
	}

}

// 返回用户信息,格式化后的字符串
func (this Customer) GetInfo() string {
	return fmt.Sprintf("%v\t%v\t%v\t%v\t%v\t%v", this.Id, this.Name, this.Gender, this.Age, this.Phone, this.Email)
}

customerService.go

package service

import (
	"customerInfo/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, "ycc", "nan", 29, "155", "ycc@qq.com")
	customerService.customers = append(customerService.customers, customer)
	return customerService
}

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

// 添加客户到客户列表切片
func (this *CustomerService) Add(name string, gender string, age int, phone string, email string) bool {
	this.customerNum++
	customer := model.NewCustomer(this.customerNum, name, gender, age, phone, email)
	this.customers = append(this.customers, customer)
	return true
}

// 根据id删除客户
func (this *CustomerService) Delete(id int) bool {
	index := this.FindById(id)
	if index == -1 {
		return false
	}
	// 如何从切片中删除一个元素
	this.customers = append(this.customers[:index], this.customers[index+1:]...)
	return true

}

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

// 根据id获取用户详细信息
func (this *CustomerService) GetById(id int) model.Customer {
	for i := 0; i < len(this.customers); i++ {
		if id == this.customers[i].Id {
			return this.customers[i]
			break
		}
	}
	return model.Customer{}
}

// 根据index更新用户详细信息
func (this *CustomerService) UpdateByIndex(index int, id int, name string, gender string, age int, phone string, email string) {
	this.customers[index] = model.Customer{
		Id:     id,
		Name:   name,
		Gender: gender,
		Age:    age,
		Phone:  phone,
		Email:  email,
	}

}

customerView.go

package main

import (
	"customerInfo/service"
	"fmt"
)

type customerView struct {
	ChoiceNum       int  // 保存用户输入的选项
	IfLogout        bool // 是否退出主菜单
	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("------------------------END------------------------\n\n\n")
}

// 得到用户的输入信息,调用add方法完成添加
func (this *customerView) add() {
	fmt.Println("----------------------添加客户----------------------")
	fmt.Printf("姓名:")
	var name string
	fmt.Scanln(&name)
	fmt.Printf("性别:")
	var gender string
	fmt.Scanln(&gender)
	fmt.Printf("年龄:")
	var age int
	fmt.Scanln(&age)
	fmt.Printf("电话:")
	var phone string
	fmt.Scanln(&phone)
	fmt.Printf("邮箱:")
	var email string
	fmt.Scanln(&email)

	if this.CustomerService.Add(name, gender, age, phone, email) {
		fmt.Printf("--------------------添加成功------------------------\n\n\n")
	} else {
		fmt.Printf("--------------------添加失败------------------------\n\n\n")
	}
}
func (this *customerView) delete() {
	fmt.Println("----------------------删除客户----------------------")
	fmt.Printf("请选择待删除客户编号(-1退出):")
	var id int
	fmt.Scanln(&id)
	if id == -1 {
		return
	}

	for {
		fmt.Printf("确认是否删除(y/n):")
		var ifExitDelete string
		fmt.Scanln(&ifExitDelete)

		if ifExitDelete == "y" || ifExitDelete == "Y" {
			// 调用customerService 的 Delete方法
			if this.CustomerService.Delete(id) {
				fmt.Println("----------------------删除完成----------------------")
				return
			} else {
				fmt.Println("----------------------删除失败,id不存在-------------")
				return
			}
		}
		if ifExitDelete == "n" || ifExitDelete == "N" {
			fmt.Println("----------------------删除取消----------------------")
			return
		}

	}

}

// 更新用户信息
func (this *customerView) update() {
	fmt.Println("----------------------修改客户----------------------")
	fmt.Printf("请选择待修改客户编号(-1退出):")
	var id int
	fmt.Scanln(&id)
	if id == -1 {
		return
	}
	index := this.CustomerService.FindById(id)
	if index == -1 {
		fmt.Println("----------------------客户不存在--------------------")
		return
	}
	customerDetail := this.CustomerService.GetById(id)
	fmt.Printf("姓名(%v):", customerDetail.Name)
	var name string = ""
	fmt.Scanln(&name)
	if name == "" {
		name = customerDetail.Name
	}
	fmt.Printf("\n性别(%v):", customerDetail.Gender)
	var gender string = ""
	fmt.Scanln(&gender)
	if gender == "" {
		gender = customerDetail.Gender
	}
	fmt.Printf("\n年龄(%v):", customerDetail.Age)
	var age int = 0
	fmt.Scanln(&age)
	if age == 0 {
		age = customerDetail.Age
	}
	fmt.Printf("\n电话(%v):", customerDetail.Phone)
	var phone string = ""
	fmt.Scanln(&phone)
	if phone == "" {
		phone = customerDetail.Phone
	}
	fmt.Printf("\n邮箱(%v):", customerDetail.Email)
	var email string = ""
	fmt.Scanln(&email)
	if email == "" {
		email = customerDetail.Email
	}
	this.CustomerService.UpdateByIndex(index, id, name, gender, age, phone, email)

}

// 显示主菜单
func (cv *customerView) mainMenu() {
	for {
		fmt.Println("------------------客户信息管理软件------------------")
		fmt.Println()
		fmt.Println("                    1 添加客户")
		fmt.Println("                    2 修改客户")
		fmt.Println("                    3 删除客户")
		fmt.Println("                    4 客户列表")
		fmt.Println("                    5 退    出")
		fmt.Println()
		fmt.Print("                    请选择(1-5):")

		fmt.Scanln(&cv.ChoiceNum)
		fmt.Println()

		switch cv.ChoiceNum {
		case 1:
			cv.add()
		case 2:
			cv.update()
		case 3:
			cv.delete()
		case 4:
			cv.list()
		case 5:
			//cv.exit()
			cv.IfLogout = true
		default:
			fmt.Println("请输入正确的选项!")
		}
		if cv.IfLogout {
			break
		}
	}
	fmt.Println("您已退出客户信息管理软件!")
}

func main() {
	// 在main函数中,创建一个customerView,并运行显示主菜单页面
	customerView := customerView{
		ChoiceNum: -1,
		IfLogout:  false,
	}
	// 这里完成对 customerView 结构体的 CustomerService 字段的初始化
	customerView.CustomerService = service.NewCustomerService()
	customerView.mainMenu()

}

文件操作

文件的基本介绍

在这里插入图片描述
在这里插入图片描述

File代表一个打开的文件对象,也被称为文件句柄(或文件指针)。

打开文件和关闭文件

在这里插入图片描述

带缓冲的Reader读文件

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

一次性读取文件

在这里插入图片描述
在这里插入图片描述

创建文件并写入内容

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

写文件的四种方式

在这里插入图片描述
2)
在这里插入图片描述
在这里插入图片描述
3)
在这里插入图片描述
4)
在这里插入图片描述

在这里插入图片描述

判断文件或目录存在

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

拷贝文件

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

统计不同类型的字符个数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

命令行参数 基本使用

在这里插入图片描述
在这里插入图片描述

flag 包解析命令行参数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

json 应用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

反序列化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

反序列化 map,不需要 make,因为 make 操作被封装到 Unmarshal 函数。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

单元测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
case001.go

package main

// 一个被测试函数
func addUpper(n int) int {
	res := 0
	for i := 1; i < n; i++ {
		res += i
	}
	return res

}

case001_test.go

package main

import "testing"

// 编写测试用例,去测试 addUpper 是否正确
func TestAddUpper(t *testing.T) {
	res := addUpper(10)
	if res != 55 {
		t.Fatalf("AddUpper(10) 执行错误,期望值=%v 实际值=%v\n", 55, res)
	}
	// 如果正确,输出日志
	t.Logf("AddUpper(10) 执行正确...")
}

在这里插入图片描述

入门总结

在这里插入图片描述
在这里插入图片描述

单元测试案例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

goroutine 协程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

案例说明

在这里插入图片描述
在这里插入图片描述
示例图
在这里插入图片描述
在这里插入图片描述

MPG模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

go 设置运行 cpu 数目

在这里插入图片描述
在这里插入图片描述

协程并发(并行)资源竞争问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

channel 管道

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基本使用

在这里插入图片描述
在这里插入图片描述

channel 是引用类型
channel 的cap(容量)是固定的,不会自动增长。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意事项:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

channel 的遍历和关闭

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

综合案例

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

管道阻塞的机制

在这里插入图片描述

协程求素数

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值