Golang学习笔记01

变量的数据类型

整数数据类型

  • 有符号类型 int8 int16 int32 int64
  • 无符号类型 uint8 uint16 uint32 uint64

浮点数据类型

  • float32 4字节
  • float64 8字节

布尔型

go 复制代码
package main

import (
	"fmt"
)

func main() {
	var s = true
	fmt.Println(s)
}

字符串

不可变:指的是字符串一旦定义好,其中字符的值不可以改变,如果输入特殊字符,字符串形式为反引号

go 复制代码
package main
func main() {
	var s1 = `
	var s = true
	println(s)`
	println(s1)
}

可以保留原有的输入的内容

类型转化

只能进行强类型转化,不支持自动类型转化,原有的类型不变,只是将数值转化

go 复制代码
package main

func main() {
	var a = 101
	var b = string(a)
	println(b)
}

注意:int64转化为int8时编译不会出错,但是数值会溢出

其他类型转化为String

使用Sprintf函数进行转化

go 复制代码
package main

import "fmt"

func main() {
	//其他类型转化为String类型
	//fmt.Sprintf()使用中需要注意转换的格式,int 为%d, float 为%f, bool为%t, byte 为%c
	var a int = 20
	var b float64 = 12.456
	var c bool = true
	var d byte = 'a'
	var stra, strb, strc, strd string
	stra = fmt.Sprintf("%d", a)
	strb = fmt.Sprintf("%f", b)
	strc = fmt.Sprintf("%t", c)
	strd = fmt.Sprintf("%c", d)
	//输出值的类型%T,占位符%v
	fmt.Printf("stra type is %T, value is %v \n", stra, stra)
	fmt.Printf("strb type is %T, value is %v \n", strb, strb)
	fmt.Printf("strc type is %T, value is %v \n", strc, strc)
	fmt.Printf("strd type is %T, value is %v \n", strd, strd)
}

使用strconv函数进行转化

go 复制代码
package main

import (
	"fmt"
	"strconv"
)

func main() {
	var n1 int = 18
	//参数:第一个参数:传入int64位的一个整数,第二个参数:你需要转化的进制数
	var s1 = strconv.FormatInt((int64(n1)), 10)
	fmt.Printf("s1对应的类型是:%T,s1 = %q", s1, s1)
	println()
	//参数:第一个参数:需要转化的数,第二个参数:'f'(-ddd.dddd),第三个参数:小数点的保留位数,第四个参数:转化为int64
	var n2 float64 = 4.21
	var s2 = strconv.FormatFloat(n2, 'f', 4, 64)
	fmt.Printf("s2对应的类型是:%T,s2 = %q", s2, s2)
	println()
	var n3 = true
	var s3 = strconv.FormatBool(n3)
	fmt.Printf("s3对应的类型是:%T,s3 = %q", s3, s3)
}

//运行结果:
//s1对应的类型是:string,s1 = "18"
//s2对应的类型是:string,s2 = "4.2100"
//s3对应的类型是:string,s3 = "true" 

string类型转化为其他类型

go 复制代码
package main

import (
	"fmt"
	"strconv"
)

func main() {
	var a = "123"
	var a1, err = strconv.ParseInt(a, 10, 64)
	fmt.Printf("类型是:%T,值是%v,%v", a1, a1, err)
	println()
	//非数字字符不能转化为int
	var b = "hello"
	var b1, err1 = strconv.ParseInt(b, 10, 64)
	fmt.Printf("类型是:%T,值是%v,%v", b1, b1, err1)
	println()
	var c = "true"
	var c1, _ = strconv.ParseBool(c)
	fmt.Printf("类型是:%T,值是%v", c1, c1)
}

指针

go 复制代码
package main

func main() {
	var i int = 10
	println("i的值", i)
	//指针类型
	var ptr *int = &i
	println("i的地址", ptr)
	println("ptr的地址", &ptr)
	println("ptr指向的值", *ptr)
}
/*
输出结果:
i的值 10
i的地址 0xc00005ff28
ptr的地址 0xc00005ff38
ptr指向的值 10
*/

注意点

  1. 指针可以改变具体的值
  2. 指针变量接受的是地址
  3. 指针的地址不可以不匹配

流程控制语句

go 复制代码
package main

import "fmt"

func main() {
	//流程控制语句
	var a = 10
	if a > 10 {
		fmt.Println(1)
	} else {
		fmt.Println(2)
	}

	//switch循环
	switch 10 / 2 {
	case 1:
		println(1)
	case 2:
		println(2)
	default:
		println(3)
	}

	//for循环
	for i := 0; i < 10; i++ {
		fmt.Printf("%v \n", i)
	}
	//for range遍历:每个结果的索引被i接收,每个结果被val接收,遍历是对字符遍历
	var str = "hello,go语言"
	for i, val := range str {
		fmt.Printf("i=%v,val=%q \n", i, val)
	}
	/*	输出为:
		i=0,val='h'
		i=1,val='e'
		i=2,val='l'
		i=3,val='l'
		i=4,val='o'
		i=5,val=','
		i=8,val='g'
		i=9,val='o'
		i=10,val='语'
		i=13,val='言'
	*/
}

goto用法

go 复制代码
package main

import "fmt"

func main() {
	fmt.Println(1)
	fmt.Println(2)
	if 1 == 1 {
		goto label1
	}
	fmt.Println(3)
	fmt.Println(4)
	label1:
	fmt.Println(5)
}

函数

go 复制代码
package main

import "fmt"

func main() {
	//调用
	var res = sum(1, 2)
	fmt.Println(res)
}

func sum(a int, b int) int {
	return a + b
}

首字母大写该函数可以被本包文件和其他包使用(public),首字母小写只能被本包使用(private)

通过地址交换两个数

go 复制代码
package main

import "fmt"

func main() {
	//调用
	var a = 10
	var b = 20
	fmt.Println(a, b)
	swap(&a, &b)
	fmt.Println(a, b)
}

func swap(a *int, b *int) {
	var t = *a
	*a = *b
	*b = t
}

ps:go中不支持重载,支持可变参数

go函数可以作为一个数据类型,赋值给一个变量

go 复制代码
package main

import "fmt"

func test(num int) {
	fmt.Println(num)
}

func main() {
	var a = test
	fmt.Printf("a的类型是%T,test的类型为%T \n", a, test) //a的类型是func(int),test的类型为func(int)10
	a(10) //等价与test(10)
}

自定义数据类型

go 复制代码
package main

import "fmt"

func main() {
	//自定义数据类型:相当于起别名
	type myInt int
	var num1 myInt = 10
	//num1的类型是main.myInt,num1的值为10
	fmt.Printf("num1的类型是%T,num1的值为%v", num1, num1)
}

函数的返回值可以支持命名,里面的顺序可以不一样

go 复制代码
package main

import "fmt"

func test1(num1 int, num2 int) (sum int, sub int) {
	sub = num1 - num2
	sum = num1 + num2
	return sum, sub
}

func main() {
	var n1 = 10
	var n2 = 5
	var sum, sub = test1(n1, n2)
	fmt.Println(sum, sub)
}

init函数

每一个源文件包含一个init函数,该函数会在main函数调用前,被go框架所执行

go 复制代码
package main

import "fmt"

func init() {
	fmt.Println("init被执行")
}

func main() {
	fmt.Println("main被执行")
}
//init被执行
//main被执行

匿名函数

只希望被调用一次,可以使用到匿名函数,定义的同时被调用

go 复制代码
package main

import "fmt"

// 让匿名函数在全局有效
var Mul = func(num1 int, num2 int) int {
	return num1 * num2
}

func main() {
	//定义匿名函数
	var res = func(num1 int, num2 int) int {
		return num1 + num2
	}(10, 20)
	fmt.Println(res)

	//将匿名函数赋值给一个变量,这个变量实际上是函数类型的变量
	//sub等价于匿名函数
	sub := func(num1 int, num2 int) int {
		return num1 - num2
	}

	//调用sub
	res01 := sub(50, 20)
	fmt.Println(res01)

	var res02 = Mul(2, 3)
	fmt.Println(res02)
}

闭包

返回的匿名函数+匿名函数以外的变量 = 闭包

闭包的值会一直保存到内存中

go 复制代码
package main

import "fmt"

// 闭包
func getSum() func(int) int {
	var n = 10
	return func(i int) int {
		n = n + i
		return n
	}
}
func main() {
	f := getSum()
	fmt.Println(f(1))//11
	fmt.Println(f(1))//12
}

defer 关键字

go 复制代码
package main

import "fmt"

func main() {
	fmt.Println(add(30, 60))
}
func add(num1 int, num2 int) int {
	//在Golang中程序遇到关键字defer不会立即执行,而是将defer后的语句压入栈中,继续执行函数后的语句
	defer fmt.Println("num1=", num1)
	defer fmt.Println("num2=", num2)

	var sum = num1 + num2
	fmt.Println("sum=", sum)
	return sum
}
/*
按照先进后出的规则
sum= 90
num2= 60
num1= 30
90
 */

应用场景:想要关闭某些资源时,在前面加入defer关键字,因为defer有延迟机制

系统函数

go 复制代码
package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main() {
	//1.统计字符串
	var str = "golang你好"  //Golang中汉字是utf-8字符集,一个汉字三个字节
	fmt.Println(len(str)) //12
	//2.对字符串进行遍历 方式一
	//索引为0,值为g
	//索引为1,值为o
	//索引为2,值为l
	//索引为3,值为a
	//索引为4,值为n
	//索引为5,值为g
	//索引为6,值为你
	//索引为9,值为好
	for i, value := range str {
		fmt.Printf("索引为%d,值为%c \n", i, value)
	}
	//方式二利用切片
	//'g''o''l''a''n''g''你''好'
	var r = []rune(str)
	for i := 0; i < len(r); i++ {
		fmt.Printf("%q", r[i])
	}
	println()
	//3.字符串转化整数
	n, _ := strconv.Atoi("66")
	fmt.Println(n)
	//4.整数转为字符串
	var str1 = strconv.Itoa(10)
	fmt.Println(str1)
	//5.统计一个字符串有多少指定的子串
	var count = strings.Count("javaandgolang", "a")
	fmt.Println(count) //4
	//6.不区分大小写的字符串的比较
	fmt.Println(strings.EqualFold("go", "GO")) //true
	//7.查看子串是否在字符串内
	var res = strings.Contains("golang", "o")
	println(res)
	//8.返回一个子串在字符串中第一次出现的索引,没有就返回-1
	var index = strings.Index("golang", "a")
	fmt.Println(index) //3
}
go 复制代码
package main

import (
	"fmt"
	"strings"
)

func main() {
	//9.字符串替换 n=-1表示全部替换,替换两个n=2
	var str = strings.Replace("golangandjava", "go", "golang", 2)
	fmt.Println(str)
	//10.切割
	var str1 = strings.Split("go-java-c++", "-")
	fmt.Println(str1) //[go java c++]
	//11.大小写转化
	strings.ToLower("A")
	strings.ToUpper("a")
	//12.去除空格
	strings.TrimSpace(" goandjava ")
	//13.去除左右两边指定字符
	strings.Trim("-javago-", "-")
	//14.判断字符是否是指定字符开头,结尾
	strings.HasPrefix("http://123.123", "http")
	strings.HasSuffix("http://123.123", "123")
}

日期函数

go 复制代码
package main

import (
	"fmt"
	"time"
)

func main() {
	//日期函数
	var now = time.Now()
	//返回值的类型是一个结构体
	fmt.Printf("类型是%T \n", now) //time.Time
	fmt.Println(now)            //2024-06-13 14:25:35.9049279 +0800 CST m=+0.002579401

	year := now.Year()
	month := now.Month()
	day := now.Day()
	fmt.Println(year, month, day)
}

内置函数

不需要导包,直接使用

go 复制代码
package main

import "fmt"

func main() {
	var str = "golang"
	fmt.Println(len(str))
	//new函数分配内存,new函数的实参是一个类型而不是具体数值,返回值是对应类型的指针
	var num = new(int)
	fmt.Printf("num的类型是%T,num的值为%v,num的地址为%v,num指向的值为%v", num, num, &num, *num)
	//num的类型是*int,num的值为0xc00000a0f8,num的地址为0xc000062030,num指向的值为0
}

错误处理机制

使用defer+recover管理错误

go 复制代码
package main

import "fmt"

func main() {
	//利用defer+recover+匿名函数捕获异常
	defer func() {
		var err = recover()
		if err != nil {
			fmt.Println("错误被捕获")
			fmt.Println("错误是", err)
		}
	}()
	var num1 = 10
	var num2 = 0
	var res = num1 / num2
	fmt.Println(res)
}

自定义错误

go 复制代码
package main

import (
	"errors"
	"fmt"
)

func main() {
	err := test()
	if err != nil {
		fmt.Println("自定义错误", err)
	}
	fmt.Println("正常执行下面逻辑")
}

func test() (err error) {
	num1 := 10
	num2 := 0
	if num2 == 0 {
		//抛出自定义异常
		return errors.New("除数不能为0")
	} else {
		fmt.Println(num1 / num2)
		return nil
	}
}
//自定义错误 除数不能为0
//正常执行下面逻辑

数组

go 复制代码
package main

import "fmt"

func main() {
	var num [3]int
	num[0] = 1
	num[1] = 2
	num[2] = 3
	var sum int
	for i := 0; i < len(num); i++ {
		sum += num[i]
	}
	fmt.Println(sum)
	//初始化数组
	var arr [3]int = [3]int{10, 11, 12}
	fmt.Println(arr)
	var arr2 = [...]int{1, 2, 3, 4}
	fmt.Println(arr2)
	var arr3 = [...]int{1: 10, 2: 1, 0: 5}
	fmt.Println(arr3)
}

数组默认是值传递,想要在外部修改原有的值,需要传递地址

go 复制代码
package main

import (
	"fmt"
)

func main() {
	var arr = [...]int{1, 2, 3}
	fmt.Println("原数组的值为", arr)
	test(&arr)
	fmt.Println("修改后数组的值为", arr)
	//原数组的值为 [1 2 3]
	//修改后数组的值为 [4 2 3]
}

func test(arr *[3]int) {
	arr[0] = 4
}

二维数组

go 复制代码
package main

import "fmt"

func main() {
	var arr = [2][3]int{{1, 2, 3}, {4, 5, 6}}
	fmt.Println(arr)
}

切片

建立在数组上的一种抽象,构建在数组之上,并且提供了更强大的能力,

是对数组一个连续片段的引用,所以切片是一种引用类型,这个片段可以是整个数组

或者是由起始和终结标识符的一些项的子集

go 复制代码
package main

import "fmt"

func main() {
	var arr = [6]int{1, 2, 3, 4, 5, 6}
	//切片构建在数组之上,左闭右开
	var slice = arr[1:3]
	fmt.Println(slice)
	//切片的构建
	var slice1 = make([]int, 4, 20)
	fmt.Println("slice1的长度", len(slice1))
	fmt.Println("slice1的最大容量", cap(slice1))

	var slice2 = []int{1, 2, 3}
	fmt.Printf("slice2的类型%T \n", slice2)
	fmt.Println("slice2的长度", len(slice2))
	fmt.Println("slice2的最大容量", cap(slice2))
}

可以实现动态扩容,底层是创建一个新数组将老数组复制到新数组中

go 复制代码
package main

import "fmt"
func main() {
	var slice2 = []int{1, 2, 3}
	var slice3 = append(slice2, 4, 5)
	fmt.Println(slice3)//1,2,3,4,5
}

映射

go中内置的数据类型,将键值进行关联,通过key获取val

go 复制代码
package main

import "fmt"

func main() {
	//只声明是不会分配内存空间的
	var a = make(map[int]string, 10)
	a[1] = "张三"
	a[2] = "李四"
	a[3] = "王五"
	fmt.Println(a)

	var b = make(map[int]string)
	b[1] = "张三"
	b[2] = "李四"
	fmt.Println(b)

	var c = map[int]string{
		1: "张三",
		2: "李四",
	}
	fmt.Println(c)
}

面向对象

go 复制代码
package main

import "fmt"

type Person struct {
	Name string
	Age  int
}

func main() {
	//方式一
	var p1 = Person{
		Name: "张三",
		Age:  18,
	}
	fmt.Println(p1)

	//方式二创建结构体的指针,应该给地址指向的字段赋值
	var p2 *Person = new(Person)
	(*p2).Name = "李四"
	(*p2).Age = 20
	fmt.Println(*p2)

	//方式三
	var p3 = &Person{
		"王五",
		30,
	}
	fmt.Println(p3)
}
go 复制代码
package main

import "fmt"

type A struct {
	Num int
}

// 方法与结构体是绑定关系,如果其他类型调用test会报错,并且是值传递
func (a A) test() {
	fmt.Println(a.Num)
}

func main() {
	var p = A{
		Num: 1,
	}
	p.test()
}

	a[3] = "王五"
	fmt.Println(a)

	var b = make(map[int]string)
	b[1] = "张三"
	b[2] = "李四"
	fmt.Println(b)

	var c = map[int]string{
		1: "张三",
		2: "李四",
	}
	fmt.Println(c)
}
相关推荐
孤寂大仙v1 小时前
【Linux笔记】理解文件系统(上)
linux·运维·笔记
ianozo1 小时前
数据结构--【栈与队列】笔记
数据结构·笔记
极客BIM工作室2 小时前
机器学校的考试风波:误差分析、过拟合和欠拟合
笔记·机器学习
flashier2 小时前
C语言 进阶指针学习笔记
c语言·笔记·学习
大白的编程日记.3 小时前
【Linux学习笔记】Linux基本指令分析和权限的概念
linux·笔记·学习
螺旋式上升abc3 小时前
GO语言学习笔记
笔记·学习·golang
W起名有点难3 小时前
前端学习——CSS
前端·css·学习
Moonnnn.4 小时前
51单片机——汇编工程建立、仿真、调试全过程
汇编·笔记·嵌入式硬件·学习·51单片机
画个逗号给明天"4 小时前
TinyWebServer项目笔记——02 半同步半反应堆线程池
笔记
不会聊天真君6474 小时前
HTML5(Web前端开发笔记第一期)
笔记·html5