后端基础_01|青训营笔记

87 阅读6分钟

后端基础_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. 直接通过对象改变;
  2. 通过指针去值去改变
	// 修改值有两种方式
	// 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关键字修饰关闭资源的语句中

系统函数

字符串

  1. len函数
str := "hello"
	fmt.Println(len(str))
  1. for-range字符串遍历
	for i, value := range str {
		fmt.Printf("%d,%c\n", i, value)
	}
  1. :=[]rune(str) 转化为一个int型数组
	r := []rune(str)
	for i := 0; i < len(r); i++ {
		fmt.Printf("%c", r[i])
	}
  1. 字符串转整数
atoi, _ := strconv.Atoi("111")
  1. 整数转字符串
itoa := strconv.Itoa(11)
  1. 查找子串是否在指定的字符串中:
strings.Contains("abc","a")
  1. 统计一个字符串有几个指定的子串
strings.Count("abc","a")
  1. 不区分大小写的字符串比较
strings.EqualFold("go" , "Go")
  1. 返回子串在字符串第一次出现的索引值,如果没有返回-1
strings.lndex("javaandgolang" , "a") 
  1. 字符串的替换
strings.Replace("goandjavagogo", "go", "golang", n) // n表示替换几个
  1. 按照指定的某个字符,为分割标识,将一个学符串拆分成字符串数组
strings.Split("go-python-java", "-")
  1. 将字符串左右两边的空格去掉
strings.TrimSpace("     go and java    ")
  1. 将字符串左右两边指定的字符去掉:
strings.Trim("~golang~ ", " ~")  
  1. 【16】判断字符串是否以指定的字符串开头
strings.HasPrefix("http://java.sun.com/jsp/jstl/fmt", "http") 				
  1. 判断字符串是否以指定的字符串结束
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个部分组成为一个结构体:

  1. 数组开始的地址(从哪开始)
  2. 切片的长度
  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)
	}