后端基础_01|青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
创建变量
- var 变量名 类型 = 数据
- var 变量名 类型
- var 变量名 = 数据
- 变量名 := 数据
- var()
- var 变量名1,变量名2,变量名3 = 数据1,数据2,数据3
类型

占位符
- %d:数字
- %s:字符串
- %f:浮点
- %t:布尔
- %c:char类型
基本数据类型
数值型
整数类型
对于有符号位的类型来说

对于无符号位的类型来说,将负的加上正的


浮点类型

字符型
使用byte来表示,但是表示的AASCII码,想要标识为元字符,需要加%c
基本数据类型之间的转化
基本数据类型(要改的)
基本数据类型转化为string
通过fmt.Printf(不同的数据类型有不同的)
var n1 int = 19
var n2 float32 = 4.78
var n3 bool = false
var n4 byte = 'a'
var s1 string = fmt.Sprintf("%d",n1)
fmt.Printf("s1对应的类型是:%T ,s1 = %q \n",s1, s1)
var s2 string = fmt.Sprintf("%f",n2)
fmt.Printf("s2对应的类型是:%T ,s2 = %q \n",s2, s2)
var s3 string = fmt.Sprintf("%t",n3)
fmt.Printf("s3对应的类型是:%T ,s3 = %q \n",s3, s3)
var s4 string = fmt.Sprintf("%c",n4)
fmt.Printf("s4对应的类型是:%T ,s4 = %q \n",s4, s4)
strconv的Formt函数
var n1 int = 18
var s1 string = strconv.FormatInt(int64(n1),10) //参数:第一个参数必须转为int64类型 ,第二个参数指定字面值的进制形式为十进制
fmt.Printf("s1对应的类型是:%T ,s1 = %q \n",s1, s1)
var n2 float64 = 4.29
var s2 string = strconv.FormatFloat(n2,'f',9,64)
//第二个参数:'f'(-ddd.dddd) 第三个参数:9 保留小数点后面9位 第四个参数:表示这个小数是float64类型
fmt.Printf("s2对应的类型是:%T ,s2 = %q \n",s2, s2)
var n3 bool = true
var s3 string = strconv.FormatBool(n3)
fmt.Printf("s3对应的类型是:%T ,s3 = %q \n",s3, s3)
string转化为基本数据类型
//string-->bool
var s1 string = "true"
var b bool
//ParseBool这个函数的返回值有两个:(value bool, err error)
//value就是我们得到的布尔类型的数据,err出现的错误
//我们只关注得到的布尔类型的数据,err可以用_直接忽略
b , _ = strconv.ParseBool(s1)
fmt.Printf("b的类型是:%T,b=%v \n",b,b)
//string---》int64
var s2 string = "19"
var num1 int64
num1,_ = strconv.ParseInt(s2,10,64)
fmt.Printf("num1的类型是:%T,num1=%v \n",num1,num1)
//string-->float32/float64
var s3 string = "3.14"
var f1 float64
f1,_ = strconv.ParseFloat(s3,64)
fmt.Printf("f1的类型是:%T,f1=%v \n",f1,f1)
//注意:string向基本数据类型转换的时候,一定要确保string类型能够转成有效的数据类型,否则最后得到的结果就是按照对应类型的默认值输出
var s4 string = "golang"
var b1 bool
b1 , _ = strconv.ParseBool(s4)
fmt.Printf("b1的类型是:%T,b1=%v \n",b1,b1)
var s5 string = "golang"
var num2 int64
num2,_ = strconv.ParseInt(s5,10,64)
fmt.Printf("num2的类型是:%T,num2=%v \n",num2,num2)
复杂数据类型
指针
Java中对象存放的也是地址,真相了值。平时取的是值。
&只不过是将对象存放的地址取出来了。
指针存放的是变量的地址
两种方式改变值:
- 直接通过对象改变;
- 通过指针去值去改变
// 修改值有两种方式
// 1. 直接通过对象修改
var change1 int = 10;
fmt.Println(change1)
change1 = 15
fmt.Println(change1)
// 2. 第二种通过指针取改
var index *int = &change1;
*index = 20
fmt.Println(*index)
条件语句
都没有括号
// if
a := 10
if a == 10 {
fmt.Println("if")
}
//switch
switch a {
case 10:
fmt.Println("switch")
}
//for
for i := 0; i < 10; i++ {
fmt.Println("for", i)
}
// for range
str := "hello"
for i, value := range str {
fmt.Printf("%d,%c,\n", i, value)
}
函数
返回剋有多个
func 函数名 (形参名 形参类型,形参名 形参类型) (返回值类型,返回值类型){
具体逻辑
}
参数
- 基本数据类型和数组默认是进行值传递,对形参的修改不会影响实参。
- 可以传入指针变量而改变实参
func changReal(index *int) {
fmt.Println("我原本的值是:", *index)
*index = 30
fmt.Println("我通过函数将值改为了:", *index)
}
- 函数也是一种数据类型,可以被赋值给一个变量,通过变量取调用函数
func main() {
f := add
fmt.Printf("%T,%T", f, add)//func(int) int
f(2)
}
// 函数也是一个基本上数据类型
func add(a int) int {
fmt.Println(a)
return a
}
- 函数也可以作为另一个函数中的形参
func test(f func(int) int, a int) {
}
- 自定义名称,就是换了个名字而已
- 可以定义返回值的名称,retrn的时候就不用再return具体的名称了,自己推断
func test1(a int, b int) (sum int, sub int) {
sum = a + b
sub = a - b
return
}
函数执行流程
- imoprt函数中的顺序
- 全局变量
- init函数
- main函数
闭包
返回的匿名函数+匿名函数以外的变量。套娃 。返回的是一个匿名函数
- 闭包引用的变量会保存在内存中,一直使用
使用
闭包在需要反复使用一个值,值不断变化的时候进行使用。
如果滥用会导致开辟新的空间,造成浪费。
defer关键字
defer修饰,压入栈中延迟执行,压入的时候会讲变量的值一同存入,不会随着后续的变化而变化。
- 经常在需呀关闭资源的时候使用,将defer关键字修饰关闭资源的语句中
系统函数
字符串
- len函数
str := "hello"
fmt.Println(len(str))
- for-range字符串遍历
for i, value := range str {
fmt.Printf("%d,%c\n", i, value)
}
- :=[]rune(str) 转化为一个int型数组
r := []rune(str)
for i := 0; i < len(r); i++ {
fmt.Printf("%c", r[i])
}
- 字符串转整数
atoi, _ := strconv.Atoi("111")
- 整数转字符串
itoa := strconv.Itoa(11)
- 查找子串是否在指定的字符串中:
strings.Contains("abc","a")
- 统计一个字符串有几个指定的子串
strings.Count("abc","a")
- 不区分大小写的字符串比较
strings.EqualFold("go" , "Go")
- 返回子串在字符串第一次出现的索引值,如果没有返回-1
strings.lndex("javaandgolang" , "a")
- 字符串的替换
strings.Replace("goandjavagogo", "go", "golang", n) // n表示替换几个
- 按照指定的某个字符,为分割标识,将一个学符串拆分成字符串数组
strings.Split("go-python-java", "-")
- 将字符串左右两边的空格去掉
strings.TrimSpace(" go and java ")
- 将字符串左右两边指定的字符去掉:
strings.Trim("~golang~ ", " ~")
- 【16】判断字符串是否以指定的字符串开头
strings.HasPrefix("http://java.sun.com/jsp/jstl/fmt", "http")
- 判断字符串是否以指定的字符串结束
strings.HasSuffix("demo.png", ".png")
日期和时间
now.
now.Year(),now.Month(),now.Day(),now.Hour(),now.Minute(),now.Second()
format
now.Format("2006/01/02 15/04/05")
异常处理
defer+recover机制处理错误

defer func() {
// 调用recover
a := recover()
// 如果没错,返回0
if a != nil {
fmt.Println("你错了,,,", a)
}
}()
erros.New函数
手动选择文字抛出异常

builtin包下内置函数:panic
中断程序

流程
在方法中通过errors.New("")手动捕获异常,返回一个error参数
-> 程序中对返回值error进行判断,如果不为nil,则用builtin包下的panic函数中断程序
数组
var 名字 [大小]类型
名字[]
for key,value := range 数组 {
//第一种:
var arr1 [3]int = [3]int{3,6,9}
//第二种:
var arr2 = [3]int{1,4,7}
//第三种:
var arr3 = [...]int{4,5,6,7}
//第四种:
var arr4 = [...]int{2:66,0:33,1:99,3:88}
注意:
数组的传递是值传递,与java不同的是(Java穿的是地址,所以会影响实参),通过形参改变的数据,实参不会变化。
如果想要通过形参改变实参的值,可以通过&将数组的地址传递给函数
切片
创建:
var a [3]int = [3]int{1,1,1}
slice:=a[1:2]
slice:=make([]int,3,10)
组成:
切片由3个部分组成为一个结构体:
- 数组开始的地址(从哪开始)
- 切片的长度
- 切片的容量
var arr = [5]int8{0, 1, 2, 3, 4}
// 切片是一个结构体
slice := arr[1:4]
fmt.Println(slice)
fmt.Printf("%p\n", &slice[0])
fmt.Printf("%p\n", &arr[1])
fmt.Printf("%p\n", &slice[1])
fmt.Printf("%p\n", &slice[2])
注意:
对于切片取地址,是自己的结构体
对于直接访问 切片[ ] 可以直接修改获取的切片的值,包括原数组
- 如果切片因为扩容导致产生了新的数组,对原数组的改变将消失
- 可以通过append向切片增加值,如果想将切片连接上切片
slice = append(slice,slce2...)
映射map
创建
var a map[int]string
a = make(map[int]string, 10)
b:=make(map[int]string,10)
c := map[int]string{
1: "1",
2: "2",
}
增删改查
名称[key] = value
delete(名称,key)
value,flag := 名称[key]
对象
构体
type 名称 struct {
变量 属性
变量 属性
}
创建对象
var 名称 结构体名称
var 名称 = 结构体名称{值,值,值}
var 名称 *结构体 = new(结构体)
方法
和一个结构体进行绑定
func (teacher Teacher) test(i int) int {
return i
}
注意:
他是值传递,不会改变原值。
想修改值,传递指针类型变量
Json
转为Json格式
json.Marshal(对象),返回的是一个数组类型
Marshal
Unmarshal
// json序列化
a := userIno{"a", 18, []string{"唱歌", "跳舞"}}
marshaler, err := json.Marshal(a)
fmt.Println(marshaler, err)
var b userIno
// 反序列化
err = json.Unmarshal(marshaler, &b)
if err != nil {
panic(err)
}
fmt.Printf("%+v", b)
类的继承封装
工厂模式
type person struct {
Name string
age int
}
// 提供构造器
func NewPerson(name string) *person {
return &person{
Name: name,
}
}
// 定义set get方法,进行校验
func (p *person) SetAge(age int) {
if age > 0 && age < 150 {
(*p).age = age
} else {
fmt.Println("年龄不合理")
}
}
func (p *person) GetAge() int {
return (*p).age
}
继承
使用内部类
// Father 继承
type Father struct {
Name string
Age int8
}
type Son1 struct {
Father
Hobby []string
}
接口
定义一个interface接口,结构体绑定一个接口名字的函数。
创建一个以interface为参数的方法,自动识别使用什么函数
// 接口
type doSomething interface {
run()
}
// 结构体绑定接口方法
type Son1 struct {
Name string
Age int8
}
func (s1 Son1) run() {
fmt.Println(s1.Name, "正在run")
}
// 对外调用接口
func whoRun(something doSomething) {
something.run()
}
断言
接口.(类型) 判断是否是这个类型
// 对外调用接口
func whoRun(something doSomething) {
switch something.(type) {
case Son1:
son1 := something.(Son1)
son1.run()
case Son2:
son2 := something.(Son2)
son2.run()
}
}
文件读取
os.ReadFile读取小型文件
bufio字符流,文件递较大时使用
open, err := os.Open("/Users/goatli/Desktop/mysql.txt")
reader := bufio.NewReader(open)
for {
readString, err2 := reader.ReadString('\n')
if err2 == io.EOF {
break
}
fmt.Println(readString)
}