Golang基础学习笔记

Golang基础学习笔记

1、下载安装

1.1、下载

Golang下载地址:https://golang.google.cn/dl/

1.2、安装

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

1.3、环境变量

# GOPATH
D:\GolandProjects

在这里插入图片描述

# Path
%GOROOT%\bin

在这里插入图片描述

# 启用Go模块支持
go env -w GO111MODULE=on
# 配置Go模块下载代理
go env -w GOPROXY=https://goproxy.cn,direct

1.5、验证安装/配置

在这里插入图片描述

1.5、hello world

在这里插入图片描述

2、变量/常量

2.1、变量

package main

import "fmt"

func main() {
    // var 变量名字 类型 = 表达式
    
    // 单个变量定义
	//var name string = "xumeng03!"
	//var name = "xumeng03!"
	//name := "xumeng03!"
    var name string
	name = "xumeng03"
	fmt.Println("hello", name)
    
    // 多个变量定义
    //var name1, name2 = "xumeng", "xumeng03"
	var (
		name1  = "xumeng03"
		name2 = "xumeng"
	)
	fmt.Println("hello", name1, name2)
}

2.2、常量

package main

import "fmt"

func main() {
    // const 变量名字 类型 = 表达式
    
	const name string="xumeng03"
	// 报错
	//name = "xumeng"
	//const name1 string
	//name1 = "aaa"
	fmt.Println("hello", name)
}

3、基本数据类型

3.1、基本类型

数据类型类型解释默认零值示例传递
bool布尔型,值为truefalsefalsevar vbool bool = true
uint88位无符号整型,取值范围为0到2550var vuint8 uint8 = 1
uint1616位无符号整型,取值范围为0到655350var vuint16 uint16 = 1
uint3232位无符号整型,取值范围为0到42949672950var vuint32 uint32 = 1
uint6464位无符号整型,取值范围为0到42949672950var vuint64 uint64 = 1
uint32位/64位无符号整型,具体位数与操作系统有关var vuint uint = 1
int88位有符号整型,取值范围为-128到1270var vint8 int8 = 2
int1616位有符号整型,取值范围为-32768到327670var vint16 int16 = 2
int3232位有符号整型,取值范围为-2147483648到21474836470var vint32 int32 = 2
int6464位有符号整型,取值范围为-9223372036854775808到92233720368547758070var vint64 int64 = 2
int32位/64位有符号整型,具体位数与操作系统有关var vint int = 2
float3232位浮点型,可以表示小数,精度为7位小数0var vfloat32 float32 = 3.14
float6464位浮点型,可以表示小数,精度为15位小数0var vfloat64 float64 = 3.14
string字符串类型,由一串Unicode码点组成“”var vstring string = “hello world!”
package main

import (
	"fmt"
	"math"
	"strconv"
)

func main() {
	// bool
	var vbool bool
	fmt.Printf("类型: %T,默认值: %t\n", vbool, vbool)

	//  uint8、uint16、uint32、uint64(uint)
	var vuint uint
	var vuint8 uint8
	var vuint16 uint16
	var vuint32 uint32
	var vuint64 uint64
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint, vuint, 0, strconv.FormatUint(math.MaxUint, 10))
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint8, vuint8, 0, math.MaxUint8)
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint16, vuint16, 0, math.MaxUint16)
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint32, vuint32, 0, math.MaxUint32)
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint64, vuint64, 0, strconv.FormatUint(math.MaxUint64, 10))

	// int8、int16、int32、int64
	var vint int
	var vint8 int8
	var vint16 int16
	var vint32 int32
	var vint64 int64
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint, vint, math.MinInt, math.MaxInt)
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint8, vint8, math.MinInt8, math.MaxInt8)
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint16, vint16, math.MinInt16, math.MaxInt16)
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint32, vint32, math.MinInt32, math.MaxInt32)
	fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint64, vint64, math.MinInt64, math.MaxInt64)

	// float32、float64
	var vfloat32 float32
	var vfloat64 float64
	fmt.Printf("类型: %T,默认值: %f\n", vfloat32, vfloat32)
	fmt.Printf("类型: %T,默认值: %f\n", vfloat64, vfloat64)

	// string(值传递)
	var vstring string
	fmt.Printf("类型: %T,默认值: %s\n", vstring, vstring)
}

3.2、基本类型转换

只有类型兼容的才可以转换!

package main

import (
    "fmt"
)

func main() {
    var vint8 int8
    var vint16 int16
    //vint16 = vint8;
    vint16 = int16(vint8);
    fmt.Printf("类型: %T,值: %d", vint16, vint16)
    
    // 大转小会有精度丢失问题
    //var vint8 int8
	//var vint16 int16 = 257
	//vint8 = int8(vint16)
	//fmt.Printf("类型: %T,值: %d", vint8, vint8)
}

4、复合数据类型

数据类型类型解释默认值示例传递
Array相同类型且长度固定的数据集合[0,0,0]var arr1 = [3]int{1, 2, 3}
Slice相同类型且长度不固定的数据集合(底层是数组,也被称为动态数组)[]var sli1= []int{1, 2, 3}引用
Map键值对[]var m = map[string]string{“ke y”: “value”}引用
Func函数类型--引用
Pointer指针类型--值/引用
Struct结构体类型--
Interface接口类型---

4.1、Array(数组)

1、初始化
package main

import (
	"fmt"
)

func main() {
	// 一维数组
	// 方法1:声明并初始化一个固定长度的数组
	// 方法2:使用数组字面量初始化数组
	var arr2 = [3]int{1, 2, 3}
	// 方法3:省略数组长度的方式初始化数组
	var arr3 = [...]int{1, 2, 3, 4, 5, 6, 7}
	// 方法4:省略数组长度的方式并使用索引初始化数组
	var arr4 = [...]int{2: 3, 4: 5}
	fmt.Println(arr1, arr2, arr3, arr4)
	// 二维数组
	var arr5 = [3][5]int{{2: 3, 4: 5}, {1, 2, 3, 4}, {1, 2, 3, 4}}
	fmt.Println(arr5)
}
2、遍历
package main

func main() {
    var arr = [...]int{1, 2, 3, 4, 5, 6, 7}
    // 方法1:for range
    for index, value := range arr {
       print("arr[", index, "]==", value, ",")
    }
    println()
    // 方法2:fori
    for index := 0; index < len(arr); index++ {
       print("arr[", index, "]==", arr[index], ",")
    }
}
3、数组操作
package main

import "fmt"

func main() {
    var arr1 = [3]int{1, 2, 3}
    // 获取数组长度
    fmt.Println(arr1, len(arr1))
    // 获取元素
	fmt.Println(arr1[0])
	// 修改元素
	arr1[0] = 101
	fmt.Println(arr1)
}

4.2、Slice(切片)

1、定义
package main

import (
	"fmt"
)

func main() {
	// 一维切片
	// 方法1:声明并初始化一个切片
	var slice1 []int
	fmt.Println(slice1)
	// 方法2:使用切片字面量初始化数组
	var slice2 = []int{1, 2, 3, 4, 5, 6, 7}
	fmt.Println(slice2)
	// 方法3:使用make函数初始化
	var slice3 = make([]int, 8)
	fmt.Println(slice3)
	// 方法4:通过数组创建切片,中括号中左开右闭(左侧不填默认为0,右侧不填默认数组长度)
	var arr1 = [3]int{1, 2, 3}
	slice4 := arr1[1:2]
	fmt.Println(slice4)
	// 方法5:通过切片创建切片
	slice5 := slice2[:3]
	fmt.Println(slice5)
	// 方法6:拼接切片创建切片
	slice6 := append(slice4, slice5...)
	fmt.Println(slice6)

	// 二维数组
	var slice7 = [][]int{{2: 3, 4: 5}, {1, 2, 3, 4}, {1, 2, 3, 4}}
	fmt.Println(slice7)
}
2、遍历
package main

func main() {
	var slice1 = []int{1, 2, 3, 4, 5, 6, 7}
	// 方法1:for range
	for index, value := range slice1 {
		print("arr[", index, "]==", value, ",")
	}
	println()
	// 方法2:fori
	for index := 0; index < len(slice1); index++ {
		print("arr[", index, "]==", slice1[index], ",")
	}
}
3、切片操作
package main

import (
	"fmt"
)

func main() {
	var slice1 = []int{1, 2, 3, 4, 5, 6, 7}
	// 切片长度,切片容量
	fmt.Println(slice1, len(slice1), cap(slice1))
	// 追加元素
	slice1 = append(slice1, 8)
	fmt.Println(slice1, len(slice1), cap(slice1))
	// 修改元素
	slice1[7] = 80
	fmt.Println(slice1, len(slice1), cap(slice1))
	// 拷贝切片
	var slice2 = make([]int, len(slice1))
	copy(slice2, slice1)	// 深拷贝,可指定索引
	slice3 := slice1	// 浅拷贝
	slice1[6] = 70
	fmt.Println(slice1, len(slice1), cap(slice1))
	fmt.Println(slice2, len(slice2), cap(slice2))
	fmt.Println(slice3, len(slice3), cap(slice3))
}

4.3、Map(映射)

1、定义
package main

import "fmt"

func main() {
	// 方法1:声明一个Map
	var map1 map[string]string
	fmt.Println(map1)
	// 方法2:使用map字面量初始化Map
	var map2 = map[string]string{"name": "xumeng03"}
	fmt.Println(map2)
	// 方法3:使用make函数初始化
	var map3 = make(map[string]string)
	fmt.Println(map3)
}
2、遍历
package main

import "fmt"

func main() {
    var map1 = map[string]string{"name": "xumeng03", "age": "23"}
    for key, value := range map1 {
       fmt.Println(key, value)
    }
}
3、map操作
package main

import "fmt"

func main() {
	var map1 = map[string]string{"name": "xumeng03"}
	fmt.Println(map1)
	// 获取值
	fmt.Println(map1["name"])
	// 添加值(如果值存在则为更新)
	map1["age"] = "23"
	fmt.Println(map1)
	// 判断key是否存在
	_, exits := map1["address"]
	fmt.Println(exits)
	// 删除
	delete(map1, "age")
	fmt.Println(map1)
	// 长度
	fmt.Println(len(map1))
}

4.4、Func(函数)

package main

import "fmt"

func main() {
	_m, _n, _result := add(1, 10)
	fmt.Println(_m, _n, _result)
	fmt.Printf("%T\n", add)
}

func add(m, n int) (_m, _n, _result int) {
	result := 0
	for i := m; i <= n; i++ {
		result += i
	}
	return m, n, result
}

4.5、Point(指针)

package main

import "fmt"

func main() {
	// &表取地址,*表取值
	a := 10
	fmt.Printf("a的值是%d,a的数据类型是%T,a的地址是%p\n", a, a, &a)
	p := &a
	fmt.Printf("p的地址是%p,p的数据类型是%T,p地址的数据是%d\n", p, p, *p)
	p1 := &p
	fmt.Printf("p1的地址是%p,p1的数据类型是%T,p1地址的数据是%p\n", p1, p1, *p1)
}

4.6、Struct(结构体)

package main

import "fmt"

func main() {
	// 方法1:声明并初始化Person
	var p1 Person = Person{}
	p1.name = "xumeng03"
	p1.age = 23
	p1.sex = true
	p1.address = "shanghai"
	fmt.Println(p1)
	// 方法2:使用字面量初始化Person
	var p2 = Person{
		"xumeng03", 23, true, "shanghai",
	}
	fmt.Println(p2)
	// 方法3:使用字面量初始化Person部分属性
	var p3 = Person{
		name: "xumeng03",
	}
	fmt.Println(p3)
}

type Person struct {
	name    string
	age     int
	sex     bool
	address string
}

4.7、接口

package main

import "fmt"

func main() {
	var j = JuniorHighStudent{
		name: "xumeng02",
	}
	study(j, "物理")
	var h = HighStudent{
		name: "xumeng03",
	}
	study(h, "化学")
}

type IStudent interface {
	study(name string) string
}

type HighStudent struct {
	name string
}

type JuniorHighStudent struct {
	name string
}

func (j JuniorHighStudent) study(name string) string {
	return j.name + " study " + name
}

func (j HighStudent) study(name string) string {
	return j.name + " study " + name
}

func study(iStudent IStudent, name string) {
	fmt.Println(iStudent.study(name))
}

5、运算符

5.1、算数运算符

package main

import (
	"fmt"
)

func main() {
	a := 9
	b := 3
	fmt.Printf("%d + %d = %d\n", a, b, a+b)
	fmt.Printf("%d - %d = %d\n", a, b, a-b)
	fmt.Printf("%d * %d = %d\n", a, b, a*b)
	fmt.Printf("%d / %d = %d\n", a, b, a/b)
	fmt.Printf("%d %% %d = %d\n", a, b, a%b)

	c := 3
	c++
	fmt.Printf("%d\n", c)
	c--
	fmt.Printf("%d", c)
}

5.2、关系运算符

package main

import (
	"fmt"
)

func main() {
	a := 9
	b := 3
	c := 3
	fmt.Printf("%d > %d ? %t\n", a, b, a > b)
	fmt.Printf("%d < %d ? %t\n", a, b, a < b)
	fmt.Printf("%d == %d ? %t\n", a, b, a == b)
	fmt.Printf("%d >= %d ? %t\n", b, b, b >= c)
	fmt.Printf("%d <= %d ? %t\n", a, b, a <= b)
	fmt.Printf("%d != %d ? %t\n", b, b, b != c)
}

5.3、逻辑运算符

func main() {
	a := 9
	b := 3
	c := 3
	fmt.Printf("%b & %d = %b\n", a, b, b, c, a > b && b == c)
	fmt.Printf("%d < %d || %d == %d ? %t\n", a, b, b, c, a < b || b != c)
}

5.4、位运算符

package main

import (
	"fmt"
)

func main() {
	a := 9
	b := 3
	// 对应位均为1,才是1,否则为0
	fmt.Printf("%b & %b = %b\n", a, b, a&b)
	// 对应位均为0,才是0,否则为1
	fmt.Printf("%b | %b = %b\n\n", a, b, a|b)
	// 对应位值不同为1,否则为0
	fmt.Printf("%b ^ %b = %b\n", a, b, a^b)
	// 按位取反
	fmt.Printf("^%b = %b\n", a, ^a)
	// 对于b的值,如果为0,则取a对应位的值,否则取0
	fmt.Printf("%b &^ %b = %b\n", a, b, a&^b)
	// a=a*2^2
	a = a << 2
	fmt.Printf("9 << 2 = %b(%d)\n", a, a)
	// a=a/2
	a = a >> 1
	fmt.Printf("36 >> 1 = %b(%d)\n", a, a)
}

5.5、赋值运算符

package main

import (
	"fmt"
)

func main() {
	a := 9
	b := 3
	a += b
	fmt.Printf("9 + 3 = %d\n", a)
	a -= b
	fmt.Printf("12 - 3 = %d\n", a)
}

6、输入/输出

6.1、输出

方法说明
fmt.Print将参数打印输出到标准输出,不进行格式化处理,参数之间用空格分隔
fmt.Println将参数打印输出到标准输出,不进行格式化处理,参数之间用空格分隔,并在最后添加换行符
fmt.Printf通过格式化字符串和参数进行输出。格式化字符串中可以包含占位符(例如%s%d等),用于指定参数的格式和位置
fmt.Sprintf通过格式化字符串和参数生成一个格式化后的字符串,而不是直接打印输出。返回生成的字符串,可以赋值给变量或作为其他函数的参数
package main

import "fmt"

func main() {
	a := 11
	fmt.Printf("类型: %T,值: %d,二进制值 %b,八进制值 %o,十进制值 %d,十六进制值 %x,十六进制值 %X\n", a, a, a, a, a, a, a)
	b := "xumeng03"
	fmt.Printf("类型: %T,值: %s\n", b, b)
	c := 'A'
	fmt.Printf("类型: %T,值: %c\n", c, c)
	d := ""
	fmt.Printf("类型: %T,地址: %p\n", d, &d)
}

6.2、输入

方法说明
fmt.Scan从标准输入中读取输入,并将解析后的值存储到指定的变量中。它需要传入指向变量的指针作为参数,并以空格为分隔符进行解析
fmt.Scanf从标准输入中按照指定的格式字符串读取输入,并将解析后的值存储到指定的变量中。
package main

import (
	"fmt"
	"strconv"
)

func main() {
	//fmt.Print("请输入名称: ")
	//var a string
	//fmt.Scan(&a)
	//fmt.Println("hello", a+"!")

	fmt.Print("请输入名称、年龄: ")
	var a string
	var b int64
	fmt.Scanf("%s %d", &a, &b)
	fmt.Println("hello", a+" "+strconv.FormatInt(b, 10)+"!")
}

7、流程控制

7.1、判断语句

1、if
package main

import (
	"fmt"
)

func main() {
	fmt.Print("请输入年龄: ")
	var b int64
	//fmt.Scanf("%d", &b)
	//if b > 18 {
	//	fmt.Print("成年")
	//} else if b == 18 {
	//	fmt.Print("刚成年")
	//} else {
	//	fmt.Print("未成年")
	//}
	if fmt.Scanf("%d", &b); b > 18 {
		fmt.Print("成年")
	} else if b == 18 {
		fmt.Print("刚成年")
	} else {
		fmt.Print("未成年")
	}
}
2、switch
package main

import (
	"fmt"
)

func main() {
	fmt.Print("请输入季度: ")
	var b int64
	fmt.Scanf("%d", &b)
	switch b {
	case 1:
		fmt.Println("第一季度")
	case 2:
		fmt.Println("第二季度")
	case 3:
		fmt.Println("第三季度")
	case 4:
		fmt.Println("第四季度")
	default:
		fmt.Println("未知季度")
	}
}
package main

import (
	"fmt"
)

func main() {
	fmt.Print("请输入月份: ")
	var b int64
	fmt.Scanf("%d", &b)
	switch {
	case b >= 1 && b < 4:
		fmt.Println("第一季度")
	case b >= 4 && b < 7:
		fmt.Println("第二季度")
	case b >= 7 && b < 10:
		fmt.Println("第三季度")
	case b >= 10 && b < 12:
		fmt.Println("第四季度")
	default:
		fmt.Println("未知季度")
	}
}
package main

import (
	"fmt"
)

func main() {
	fmt.Print("请输入月份: ")
	var b int64
	fmt.Scanf("%d", &b)
	switch b {
	case 1, 2, 3:
		fmt.Println("第一季度")
	case 4, 5, 6:
		fmt.Println("第二季度")
	case 7, 8, 9:
		fmt.Println("第三季度")
	case 10, 11, 12:
		fmt.Println("第四季度")
	default:
		fmt.Println("未知季度")
	}
}
package main

import (
	"fmt"
)

func main() {
	fmt.Print("请输入月份: ")
	var b int64
	fmt.Scanf("%d", &b)
	switch b {
	case 1, 2, 3:
		fmt.Println("第一季度")
		fmt.Println("第一季度")
		// 穿透case
		fallthrough
	case 4, 5, 6:
		fmt.Println("第二季度")
		fmt.Println("第二季度")
	case 7, 8, 9:
		fmt.Println("第三季度")
		// 强制结束case
		break
		fmt.Println("第三季度")
	case 10, 11, 12:
		fmt.Println("第四季度")
	default:
		fmt.Println("未知季度")
	}
}

7.2、循环语句

1、for
package main

import (
	"fmt"
)

func main() {
	fmt.Print("请输入数字: ")
	var b int
	fmt.Scanf("%d", &b)
	for a := 1; a <= b; a++ {
		fmt.Println(a)
	}
}
package main

import (
	"fmt"
)

func main() {
	fmt.Print("请输入数字: ")
	var b int
	fmt.Scanf("%d", &b)
	//for a := 1; a <= b; a++ {
	//	fmt.Println(a)
	//}
	a := 1
    // 相当于while循环
	for a <= b {
		fmt.Println(a)
		a++
	}
}
// 九九乘法表
package main

import "fmt"

func main() {
	for a := 1; a < 10; a++ {
		for b := 1; b <= a; b++ {
			if b > 0 {
				fmt.Print(" ")
			}
			fmt.Printf("%d*%d=%d", a, b, a*b)
		}
		fmt.Println()
	}
}
// 水仙花数
package main

import "fmt"

func main() {
	for a := 100; a < 1000; a++ {
		b := a
		result := 0
		for ; b != 0; b = b / 10 {
			c := b % 10
			result += c * c * c
		}
		if result == a {
			fmt.Println(a)
		}
	}
}
// 素数
package main

func main() {
	count := 0
	for a := 2; a <= 100; a++ {
		var b = 2
		for ; b < a; b++ {
			if a%b == 0 {
				break
			}
		}
		if b == a {
			println(a)
			count++
		}
	}
	println("总数:", count)
}
2、goto

暂不介绍

8、函数

函数也属于复合类型

8.1、基础使用

package main

import "fmt"

func main() {
	_m, _n, _result := add(1, 10)
	fmt.Println(_m, _n, _result)
}

// 具名返回值可直接return
func add(m, n int) (_m, _n, _result int) {
	result := 0
	for i := m; i <= n; i++ {
		result += i
	}
	return m, n, result
}

8.2、可变参数

package main

import "fmt"

func main() {
	fmt.Println(add1(1, 2, 100))
}

// 只能有一个,且必须是最后一个
func add1(m ...int) ([]int, int) {
	result := 0
	for _, v := range m {
		result += v
	}
	return m, result
}

8.3、匿名函数

package main

import "fmt"

func main() {
	fmt.Println("主函数。。。")
	func() {
		fmt.Println("匿名函数。。。")
	}()
}
package main

import "fmt"

func main() {
	fmt.Println("主函数。。。")
	var fun = func() {
		fmt.Println("匿名函数。。。")
	}
	fun()
	fun()
}

8.4、递归函数

package main

func main() {
	println(fibonacci(12))
}

// fibonacci
func fibonacci(n int) (_result int) {
	if n == 1 || n == 2 {
		return 1
	}
	return fibonacci(n-1) + fibonacci(n-2)
}
package main

func main() {
	println(nn(5))
}

func nn(n int) int {
	if n == 1 {
		return 1
	}
	return n * nn(n-1)
}

8.5、回调函数

package main

func main() {
	_, _, result := callback(1, 10, add)
	print(result)
}

func add(m, n int) (_m, _n, _result int) {
	result := 0
	for i := m; i <= n; i++ {
		result += i
	}
	return m, n, result
}

func callback(m, n int, fun func(int, int) (int, int, int)) (_m, _n, _result int) {
	return fun(m, n)
}

8.6、defer

将指定函数放入任务栈,延迟函数在父级函数return前执行(注意是延迟执行,不是延迟调用)

package main

func main() {
	iprint(1)
	iprint(2)
	defer iprint(3)
	iprint(4)
	iprint(5)
	defer iprint(6)	// 1 2 4 5 6 3
}

func iprint(n int) {
	println(n)
}

8.7、闭包

package main

import "fmt"

func main() {
	result := add(10)
	fmt.Println(result()) // 1
	fmt.Println(result()) // 2
}

func add(n int) func() int {
	result := n
	return func() int {
		result += 1
		return result
	}
}

9、指针

9.1、基本使用

package main

import "fmt"

func main() {
	// &表取地址,*表取值
	a := 10
	fmt.Printf("a的值是%d,a的数据类型是%T,a的地址是%p\n", a, a, &a)
	p := &a
	fmt.Printf("p的地址是%p,p的数据类型是%T,p地址的数据是%d\n", p, p, *p)
	p1 := &p
	fmt.Printf("p1的地址是%p,p1的数据类型是%T,p1地址的数据是%p\n", p1, p1, *p1)
}

9.2、数组指针/指针数组

package main

import "fmt"

func main() {
	a := [3]string{"xumeng03", "xumeng02", "xumeng01"}
	b := [3]string{"xumeng03", "xumeng02", "xumeng01"}
	c := [3]string{"xumeng03", "xumeng02", "xumeng01"}
	fmt.Printf("a的值是%d,a的数据类型是%T,a的地址是%p\n", a, a, &a)
	// 数组指针
	p := &a
	fmt.Printf("p的地址是%p,p的数据类型是%T,p地址的数据是%d\n", p, p, *p)
	// 指针数组
	var p1 = []*[3]string{&a, &b, &c}
	fmt.Printf("p1的地址是%p,p1的数据类型是%T,p1地址的数据是%d\n", p1, p1, p1)
}

9.3、函数指针/指针函数

package main

import "fmt"

func main() {
	// 函数指针
	fmt.Printf("%p\n", a)
	// 指针函数
	i := b()
	fmt.Printf("%p %v", i, i)
}

func a() {
	fmt.Println("a...")
}

func b() *[4]int {
	a := [4]int{1, 2, 3, 4}
	fmt.Printf("%p\n", &a)
	return &a
}

9.4、指针作为参数

package main

func main() {
	var n = 1
	a(n)
	println(n)
	b(&n)
	println(n)
}

func a(n int) {
	n = 10
}

func b(p *int) {
	*p = 10
}

10、结构体

结构体属于值类型

10.1、基础使用

package main

import "fmt"

func main() {
	// 方法1:声明并初始化Person
	var p1 Person = Person{}
	p1.name = "xumeng03"
	p1.age = 23
	p1.sex = true
	p1.address = "shanghai"
	fmt.Println(p1)
	// 方法2:使用字面量初始化Person
	var p2 = Person{
		"xumeng03", 23, true, "shanghai",
	}
	fmt.Println(p2)
	// 方法3:使用字面量初始化Person部分属性
	var p3 = Person{
		name: "xumeng03",
	}
	fmt.Println(p3)
}

type Person struct {
	name    string
	age     int
	sex     bool
	address string
}

10.2、结构体指针

package main

import "fmt"

func main() {
	var p1 = Person{
		"xumeng03", 23, true, "shanghai",
	}
	fmt.Println(p1)

	var pp1 *Person = &p1
	// (*pp1).name = "Xumeng03"
	pp1.name = "Xumeng03"
	fmt.Println(p1, pp1)

	var pp2 *Person = new(Person)
	pp2 = &p1
	// (*pp1).name = "Xumeng03"
	pp2.age = 24
	fmt.Println(p1, pp2)
}

type Person struct {
	name    string
	age     int
	sex     bool
	address string
}

10.3、匿名结构体

package main

import "fmt"

func main() {
    // 匿名结构体
	var s1 = struct {
		name string
		age  int
	}{"xumeng03", 23}
	fmt.Println(s1, s1.name)
}

10.4、匿名字段

package main

import "fmt"

func main() {
	// 匿名字段(一个类型只能有一个)
	var s1 = struct {
		string
		int
	}{"xumeng03", 23}
	fmt.Println(s1, s1.string)
}

10.5、结构体嵌套

package main

import "fmt"

func main() {
	//var p1 = Person{
	//	name: "xumeng03",
	//	age:  23,
	//	sex:  true,
	//	address: Address{
	//		name: "shanghai",
	//	},
	//}
	var p1 = Person{
		"xumeng03",
		23,
		true,
		&Address{
			name: "shanghai",
		},
	}
	fmt.Println(p1)
}

type Person struct {
	name string
	age  int
	sex  bool
	//address Address
    // 防止值传递
	address *Address
}

type Address struct {
	name string
}

10.6、方法

package main

import "fmt"

func main() {
	//var p1 = Person{
	//	name: "xumeng03",
	//	age:  23,
	//	sex:  true,
	//	address: Address{
	//		name: "shanghai",
	//	},
	//}
	var p1 = Person{
		"xumeng03",
		23,
		true,
	}
	fmt.Println(p1.hello("bilibili"))
}

type Person struct {
	name string
	age  int
	sex  bool
}

func (p Person) hello(name string) string {
	return p.name + "向 " + name + " 打招呼!"
}

10.7、结构体中的继承

package main

import "fmt"

func main() {
	var p1 = Person{
		"xumeng03",
		23,
		true,
	}
	fmt.Println(p1.hello("bilibili"))

	var s1 = Student{
		Person{
			"xumeng03",
			23,
			true,
		},
		10010,
		"眼眸流转",
		"安阳师范学院",
	}
	fmt.Println(s1.name, s1.age, s1.hello("bilibili")) // 继承了Person的方法,如果Student中有与Person同名的方法或者属性,则为覆盖。
}

type Person struct {
	name string
	age  int
	sex  bool
}

type Student struct {
	Person
	num    int
	name   string
	school string
}

func (p Person) hello(name string) string {
	return p.name + "向 " + name + " 打招呼!"
}

11、接口

11.1、基础使用

package main

import "fmt"

func main() {
	var j = JuniorHighStudent{
		name: "xumeng02",
	}
	study(j, "物理")
	var h = HighStudent{
		name: "xumeng03",
	}
	study(h, "化学")
}

type IStudent interface {
	study(name string) string
}

type HighStudent struct {
	name string
}

type JuniorHighStudent struct {
	name string
}

// 接口实现
func (j JuniorHighStudent) study(name string) string {
	return j.name + " study " + name
}

// 接口实现
func (j HighStudent) study(name string) string {
	return j.name + " study " + name
}

func study(iStudent IStudent, name string) {
	fmt.Println(iStudent.study(name))
}

11.2、接口继承

package main

import "fmt"

func main() {
	var j = JuniorHighStudent{
		name: "xumeng02",
	}
	study(j, "物理")
	var h = HighStudent{
		name: "xumeng03",
	}
	study(h, "化学")
}

type IStudent interface {
	study(name string) string
}

// IStudent1 接口继承
type IStudent1 interface {
	IStudent
	study1(name string) string
}

type HighStudent struct {
	name string
}

type JuniorHighStudent struct {
	name string
}

// 接口实现
func (j JuniorHighStudent) study(name string) string {
	return j.name + " study " + name
}

// 接口实现
func (j HighStudent) study(name string) string {
	return j.name + " study " + name
}

func study(iStudent IStudent, name string) {
	fmt.Println(iStudent.study(name))
}

11.3、接口断言

package main

import (
	"fmt"
	"math"
)

func main() {
	var t Shape = Triangle{3, 4, 5}
	fmt.Println(t.Perimeter(), t.Area())
	InterfaceType(&t)

	var c Shape = Circle{5}
	fmt.Println(c.Perimeter(), c.Area())
	InterfaceType(&c)

	var s Shape = Square{5}
	fmt.Println(s.Perimeter(), s.Area())
	InterfaceType(&s)
}

type Shape interface {
	Perimeter() float64
	Area() float64
}

// Triangle 三角形
type Triangle struct {
	a, b, c float64
}

func (t Triangle) Perimeter() float64 {
	return t.a + t.b + t.c
}

func (t Triangle) Area() float64 {
	var p = t.Perimeter() / 2
	return math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
}

// Circle 圆形
type Circle struct {
	r float64
}

func (c Circle) Perimeter() float64 {
	return 2 * c.r * math.Pi
}

func (c Circle) Area() float64 {
	return math.Pow(c.r, 2) * math.Pi
}

// Square 正方形
type Square struct {
	s float64
}

func (s Square) Perimeter() float64 {
	return 4 * s.s
}

func (s Square) Area() float64 {
	return math.Pow(s.s, 2)
}

// InterfaceType 接口断言
func InterfaceType(shape *Shape) {
	// 方法1
	//if _, ok := (*shape).(Triangle); ok {
	//	fmt.Println("三角形")
	//} else if _, ok := (*shape).(Circle); ok {
	//	fmt.Println("圆形")
	//} else if _, ok := (*shape).(Square); ok {
	//	fmt.Println("正方形")
	//} else {
	//	fmt.Println("未知形状")
	//}

	// 方法2
	switch (*shape).(type) {
	case Triangle:
		fmt.Println("三角形")
	case Circle:
		fmt.Println("圆形")
	case Square:
		fmt.Println("正方形")
	default:
		fmt.Println("未知形状")
	}
}

11.4、接口嵌套

package main

func main() {
}

type V1 interface {
	v1()
}

type V2 interface {
	V1
	v2()
}

type V3 interface {
	V2
	v3()
}

12、自定义类型

package main

import "fmt"

func main() {
	var a iint = 100
	// var b int = a
	fmt.Println(a)

	var aa mint = 100
	var bb int = aa
	fmt.Println(bb)
}

// 自定义类型
type iint int

// 类型别名
type mint = int

13、异常/错误

13.1、基础使用

package main

import (
	"fmt"
	"os"
)

func main() {
	open, err := os.Open("1.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(open.Name(), "open success!")
}

13.2、自定义异常

package main

import (
	"fmt"
)

func main() {
	err1 := prime(3)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	fmt.Println("=====================")
	err2 := prime(1)
	if err2 != nil {
		fmt.Println(err2)
		return
	}
}

func prime(n int) error {
	if n < 2 {
		// 方法1:errors.New
		//err := errors.New("不合法数字!")
		// 方法2:
		err := fmt.Errorf("不合法数字!%d", 100)
		return err
	}
	var i int
	for i = 2; i < n; i++ {
		if n%i == 0 {
			break
		}
	}
	if i >= n {
		fmt.Println("是素数")
	} else {
		fmt.Println("不是素数")
	}
	return nil
}
package main

import (
	"fmt"
	"strconv"
)

func main() {
	b, err := prime(1)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(b)
}

type PrimeError struct {
	int
	string
}

func (e PrimeError) Error() string {
	return strconv.FormatInt(int64(e.int), 10) + "是非法数字!"
}

func prime(n int) (bool, *PrimeError) {
	if n < 2 {
		return false, &PrimeError{n, "非法数字"}
	}
	var i int
	for i = 2; i < n; i++ {
		if n%i == 0 {
			break
		}
	}
	if i >= n {
		return true, &PrimeError{n, "是素数"}
	} else {
		return false, &PrimeError{n, "不是素数"}
	}
}

13.3、自定义错误(panic/recover)

package main

import "fmt"

func main() {
	defer println("start")
	fori(20)
	defer println("end")
	println("bilibili")
}

func fori(n int) {
	defer func() {
		if a := recover(); a != nil {
			fmt.Println(a, "恢复运行")
		}
	}()
	defer println("fori...start")
	for i := 0; i < n; i++ {
		fmt.Println(i)
		if i == 10 {
			// 恐慌,只有panic前所有defer都被执行后,panic才会被传递到调用处
			panic("遇到了10!")
		}
	}
	defer println("fori...end")
}

14、并发编程

并发:同时处理多个任务(单处理器,也就是说一个时间点只做一件事,但是多个任务交替)

并行:同时执行多个任务(多处理器,也就是说一个时间点做多件事,多个任务同时进行)

不要使用共享内存的方式通信,而要以通信的方式共享内存!

14.1、基本使用

协程执行的函数一般没有返回值,即是有也会被舍弃

package main

import "fmt"

func main() {
	go iPrint("\tgoroutine1")
	go iPrint("\tgoroutine2")
  // 默认情况下主goroutine并不会等待其他goroutine执行完毕才结束
  // 因此此处goroutine1和goroutine2有可能未执行完成
	iPrint("主goroutine")
}

func iPrint(str string) {
	for i := 0; i < 50; i++ {
		fmt.Println(str, "打印", i)
	}
}

14.2、无缓冲通道

package main

import (
	"fmt"
)

// 无缓冲通道,读取和发送都会阻塞通道
var channel = make(chan string)

func push(str string) {
	fmt.Println("开始发送数据")
	channel <- str
	fmt.Println("发送数据完成")
}

func pop() {
	fmt.Println("开始读取数据")
	fmt.Println(<-channel)
	fmt.Println("读取数据完成")
}

func main() {
	// 读取阻塞
	//go push("xumeng03")
	//pop()

	// 发送阻塞
	go pop()
	go pop()
	go pop()
	push("xumeng01")
	push("xumeng02")
	push("xumeng03")
}
package main

import (
	"fmt"
	"strconv"
	"time"
)

// 无缓冲通道,读取和发送都会阻塞通道,容量为0
var channel = make(chan string)

func main() {
	go func() {
		for i := 0; i < 10; i++ {
			//time.Sleep(time.Second)
			channel <- "xumeng" + strconv.Itoa(i)
			fmt.Println("数据已压入通道", time.Now().Format("2006-01-02 15:04:05"))
		}
		// 关闭通道
		close(channel)
	}()

	for s := range channel {
		time.Sleep(time.Second)
		fmt.Println(s, time.Now().Format("2006-01-02 15:04:05"))
	}
}

14.3、缓冲通道

package main

import (
	"fmt"
	"strconv"
	"time"
)

// 缓冲通道,发送数据时若缓冲区已满则阻塞,接收数据若缓冲区为空则阻塞
var channel = make(chan string, 5)

func main() {
	go func() {
		for i := 0; i < 100; i++ {
			channel <- "xumeng" + strconv.Itoa(i)
			fmt.Println("数据已压入通道", time.Now().Format("2006-01-02 15:04:05"))
		}
		// 关闭通道
		close(channel)
	}()

	for s := range channel {
		time.Sleep(time.Second)
		fmt.Println(s, time.Now().Format("2006-01-02 15:04:05"))
	}
}

14.4、定向通道

主要用于传参数参数类型,保护数据

package main

// 定向通道
var rchannel = make(<-chan string)
var wchannel = make(chan<- string)

func main() {
	// 不可写入
	//rchannel <- "111"

	// 不可读取
	//<-wchannel
}
package main

import "fmt"

func main() {
	var channel = make(chan int)
	go func() {
		for i := 0; i < 100; i++ {
			push(channel, i)
		}
		close(channel)
	}()
	for n := range channel {
		fmt.Println(n)
	}
}

func push(channel chan<- int, n int) {
	channel <- n
}

func pop(channel <-chan int) {
	fmt.Println(<-channel)
}

14.5、select

package main

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

func main() {

	var c1 = make(chan int)
	var c2 = make(chan int)
	go func() {
		rand.NewSource(time.Now().UnixNano())
		time.Sleep(10 * time.Second)
		c1 <- rand.Intn(100)
	}()

	go func() {
		rand.NewSource(time.Now().UnixNano())
		time.Sleep(10 * time.Second)
		c2 <- rand.Intn(100)
	}()

	select {
	case n := <-c1:
		fmt.Println("c1", n)
	case n := <-c2:
		fmt.Println("c2", n)
	case <-time.After(5 * time.Second):
		fmt.Println("timeout!")
	}
}

15、内置包

标准库 - Go 包:https://pkg.go.dev/std

15.1、fmt

1、Print/Println/Sprint/Sprintln

func Print(a ...any) (n int, err error) 打印数据,不换行

package main

import "fmt"

func main() {
	fmt.Print("hello world")
	s1 := fmt.Sprint("hello world")
	fmt.Print(s1)
	fmt.Println("hello world")
	s2 := fmt.Sprintln("hello world")
	fmt.Print(s2)
}
2、Printf/Sprintf

func Printf(format string, a ...any) (n int, err error) 打印格式化数据

package main

import "fmt"

func main() {
	a := 11
	fmt.Printf("类型: %T,值: %d,二进制值 %b,八进制值 %o,十进制值 %d,十六进制值 %x,十六进制值 %X,地址 %p\n", a, a, a, a, a, a, a, &a)
    a1 := fmt.Sprintf("类型: %T,值: %d,二进制值 %b,八进制值 %o,十进制值 %d,十六进制值 %x,十六进制值 %X,地址 %p", a, a, a, a, a, a, a, &a)
	fmt.Println(a1)
	s := "hello world"
	fmt.Printf("类型: %T,值: %s,地址 %p\n", s, s, &s)
    s1 := fmt.Sprintf("类型: %T,值: %s,地址 %p", s, s, &s)
	fmt.Println(s1)
}

15.2、strings

字符串相关函数

1、Compare

func Compare(a, b string) int 按字典顺序比较两个字符串, 如果 a == b,则结果为 0;如果 a < b,则结果为 -1;如果 a > b,则结果为 +1。

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.Compare("a", "b"))	// -1
	fmt.Println(strings.Compare("a", "a"))	// 0
	fmt.Println(strings.Compare("b", "a"))	// 1
}
2、Contains/ContainsAny

func Contains(s, substr string) bool 判断包含 substr 是否在 s 内

func ContainsAny(s, chars string) bool 判断s中是否包含chars中的任意一个字符

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.Contains("seafood", "foo"))	// true
    fmt.Println(strings.Contains("seafood", "bar"))	// false
    fmt.Println(strings.Contains("seafood", ""))	// true
    fmt.Println(strings.Contains("", ""))	// true
    
    fmt.Println(strings.ContainsAny("team", "i"))	// false
    fmt.Println(strings.ContainsAny("fail", "ui"))	// true
    fmt.Println(strings.ContainsAny("ure", "ui"))	// true
    fmt.Println(strings.ContainsAny("failure", "ui"))	// true
    // chars是空字符串,因此没有任何字符可以在其中进行匹配。所以无论s是什么字符串,都不会在空字符串中存在匹配的字符
    fmt.Println(strings.ContainsAny("foo", ""))	// false
    fmt.Println(strings.ContainsAny("", ""))	// false
}
3、Count

func Count(s, substr string) int 判断s中是否包含chars中的任意一个字符

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.Count("cheese", "e"))	// 3
	// 如果 substr 为空字符串,则 Count 返回 1 + len(s)
	fmt.Println(strings.Count("five", ""))	// 5
}
4、Cut/CutPrefix/CutSuffix

func Cut(s, sep string) (before, after string, found bool) 在s中根据sep切割字符串并返回前、后、是否查询到切割字符

package main

import (
	"fmt"
	"strings"
)

func main() {
	show := func(s, sep string) {
		before, after, found := strings.Cut(s, sep)
		fmt.Printf("%q, %q, %v\n", before, after, found)
	}
	show("Gopher", "Go")	// "", "pher", true
	show("Gopher", "ph")	// "Go", "er", true
	show("Gopher", "er")	// "Goph", "", true
    // 如未找到,after=s
	show("Gopher", "Badger")	// "Gopher", "", false
}

func CutPrefix(s, prefix string) (after string, found bool) 判断s是否以sep开头,如是则返回切割后结果,如不是则返回s

package main

import (
	"fmt"
	"strings"
)

func main() {
	show := func(s, sep string) {
		after, found := strings.CutPrefix(s, sep)
		fmt.Printf("CutPrefix(%q, %q) = %q, %v\n", s, sep, after, found)
	}
	show("Gopher", "Go")	// "pher", true
	show("Gopher", "ph")	// "Gopher", false
}

func CutSuffix(s, suffix string) (before string, found bool) 判断s是否以s结尾,如是则返回切割后结果,如不是则返回s

package main

import (
    "fmt"
    "strings"
)

func main() {
    show := func(s, sep string) {
       before, found := strings.CutSuffix(s, sep)
       fmt.Printf("CutSuffix(%q, %q) = %q, %v\n", s, sep, before, found)
    }
    show("Gopher", "Go")   // "Gopher", false
    show("Gopher", "er")   // "Goph", true
}
5、EqualFold

func EqualFold(s, t string) bool 判断s和t是否相等(忽略大小写)

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.EqualFold("Go", "go"))
    fmt.Println(strings.EqualFold("AB", "ab")) // true
    fmt.Println(strings.EqualFold("ß", "ss"))  // false
}
6、Fields

func Fields(s string) []string 根据空格分隔s

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz   "))  // ["foo" "bar" "baz"]
}
7、HasPrefix/HasSuffix

func HasPrefix(s, prefix string) bool 判断s是否以prefix 开头

func HasSuffix(s, suffix string) bool 判断s是否以suffix结尾

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.HasPrefix("Gopher", "Go"))	// true
	fmt.Println(strings.HasPrefix("Gopher", "C"))	// false
	fmt.Println(strings.HasPrefix("Gopher", ""))	// true
    
    fmt.Println(strings.HasSuffix("Amigo", "go"))  // true
    fmt.Println(strings.HasSuffix("Amigo", "O"))   // false
    fmt.Println(strings.HasSuffix("Amigo", "Ami")) // false
    fmt.Println(strings.HasSuffix("Amigo", ""))    //true
}
8、Index/LastIndex

func Index(s, substr string) int返回 s 中第一个 substr 的索引,如果不存在,则返回 -1

func LastIndex(s, substr string) int 返回 s 中最后一个 substr 实例的索引,如果 s 中不存在 substr,则返回 -1

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.Index("chicken", "ken"))	// 4
	// 未检索到,则返回-1
	fmt.Println(strings.Index("chicken", "dmr"))	// -1
    
    fmt.Println(strings.LastIndex("go gopher", "go"))     // 3
	fmt.Println(strings.LastIndex("go gopher", "rodent")) // -1
}
9、Join

func Join(elems []string, sep string) string 以sep作为分隔符,拼接string数组

package main

import (
	"fmt"
	"strings"
)

func main() {
	s := []string{"foo", "bar", "baz"}
	fmt.Println(strings.Join(s, ","))	// foo,bar,baz
}
10、Repeat

func Repeat(s string, count int) string 返回一个重复count次的s字符串

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println("ba" + strings.Repeat("na", 2))	// banana
}
11、Replace/ReplaceAll

func Replace(s, old, new string, n int) string 在s中使用new替换old,最多替换n次

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
    // n<0 则表示全局替换
    fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
}

func ReplaceAll(s, old, new string) string 在s中使用new替换所有old

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ReplaceAll("oink oink oink", "oink", "moo"))
}
12、Split/SplitAfter

func Split(s, sep string) []string 使用sep分割s,返回string数组

func SplitAfter(s, sep string) []string 使用sep分割s,返回string数组(保留分隔符)

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Printf("%q\n", strings.Split("a,b,c", ","))
	fmt.Printf("%q\n", strings.SplitAfter("a,b,c", ","))
}
13、ToUpper/ToLower

func ToUpper(s string) string 将s转为大写

func ToLower(s string) string 将s转为小写

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ToUpper("Gopher"))
    fmt.Println(strings.ToLower("Gopher"))
}
14、Trim/TrimLeft/TrimRight/TrimSpace

func Trim(s, cutset string) string 清除s中cutset中存在的字符

func TrimLeft(s, cutset string) string 清除s左侧所有中cutset中存在的字符,直至第一个非cutset中存在的字符

func TrimRight(s, cutset string) string 清除s右侧所有中cutset中存在的字符,直至第一个非cutset中存在的字符

func TrimSpace(s string) string 清楚s中空格、换行、制表符

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Print(strings.Trim("¡¡¡Hello, Gophers!!!", "!¡"))
    fmt.Print(strings.TrimLeft("¡¡¡Hello, Gophers!!!", "!¡"))
    fmt.Print(strings.TrimRight("¡¡¡Hello, Gophers!!!", "!¡"))
    fmt.Println(strings.TrimSpace(" \t\n Hello, Gophers \n\t\r\n"))
}

15.3、strconv

基本类型的转换

1、Atoi/Itoa

func Atoi(s string) (int, error) 将字符串转为int

func Itoa(i int) string 将int转为字符串

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var a = 1
	fmt.Println(strconv.Itoa(a))
	var b = "10"
	fmt.Println(strconv.Atoi(b))
}
2、FormatInt/FormatFloat/FormatBool

func FormatInt(i int64, base int) string 将int转为string

func FormatFloat(f float64, fmt byte, prec, bitSize int) string 将float转为string

func FormatBool(b bool) string 将bool转为string

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var a int64 = 1
	fmt.Println(strconv.FormatInt(a, 10))
	var b = 3.14
	fmt.Println(strconv.FormatFloat(b, 'g', -1, 64))
	var c = true
	fmt.Println(strconv.FormatBool(c))
}
3、ParseInt/ParseFloat/ParseBool

func ParseInt(s string, base int, bitSize int) (i int64, err error) 将字符串解析为int

func ParseFloat(s string, bitSize int) (float64, error) 将字符串解析为float

func ParseBool(str string) (bool, error) 将字符串解析为bool

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var a = "1"
	fmt.Println(strconv.ParseInt(a, 10, 64))
	var b = "3.14"
	fmt.Println(strconv.ParseFloat(b, 10))
	var c = "true"
	fmt.Println(strconv.ParseBool(c))
}

15.4、time

1、Now

func Now() Time 获取当前时间

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println(time.Now())
}
2、Date

func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time 获取指定的时间

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println(time.Date(2023, 10, 30, 22, 22, 22, 0, time.UTC))
	fmt.Println(time.Date(2023, 10, 30, 22, 22, 22, 0, time.Local))
}
3、Format

func (t Time) Format(layout string) string 格式化时间

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
}
4、Parse

func Parse(layout, value string) (Time, error) 将字符串解析为时间

package main

import (
	"fmt"
	"time"
)

func main() {
	var str = "2023-10-30 10:00:00"
	parse, err := time.Parse("2006-01-02 15:04:05", str)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(parse)
}
5、Date/Clock

func (t Time) Date() (year int, month Month, day int) 获取时间的年月日

func (t Time) Clock() (hour, min, sec int) 获取时间的时分秒

package main

import (
    "fmt"
    "time"
)

func main() {
    var t = time.Now()
    year, month, day := t.Date()
    hour, min, sec := t.Clock()
    fmt.Println(year, month, day)
    fmt.Println(hour, min, sec)
}
6、Year/Month/Day/Hour/Minute/Second/Nanosecond/YearDay/Weekday

func (t Time) Year() int 获取时间的年份

func (t Time) Month() Month 获取时间的月份

func (t Time) Day() int 获取时间的日期

func (t Time) Hour() int 获取时间的小时

func (t Time) Minute() int 获取时间的分钟

func (t Time) Second() int 获取时间的秒钟

func (t Time) Nanosecond() int 获取时间的纳秒

func (t Time) YearDay() int 获取时间的在年份中的天数

func (t Time) Weekday() Weekday 获取时间是周几

package main

import (
    "fmt"
    "time"
)

func main() {
    var t = time.Now()
    fmt.Println("年份", t.Year())
    fmt.Println("月份", t.Month())
    fmt.Println("日期", t.Day())
    fmt.Println("时", t.Hour())
    fmt.Println("分", t.Minute())
    fmt.Println("秒", t.Second())
    fmt.Println("纳秒", t.Nanosecond())
    fmt.Println("此年份第", t.YearDay(), "天")
    fmt.Println("当天是", t.Weekday())
}
7、Unix/UnixNano

func (t Time) Unix() int64 获取时间距1970-1-1 00:00:00的时间差值(单位:秒)

func (t Time) UnixNano() int64 获取时间距1970-1-1 00:00:00的时间差值(单位:纳秒)

package main

import (
    "fmt"
    "time"
)

func main() {
    var t = time.Now()
    fmt.Println(t.Unix())
    fmt.Println(t.UnixNano())
}
8、Add/AddDate

func (t Time) Add(d Duration) Time 在当前时间基础添加/减少时间

func (t Time) AddDate(years int, months int, days int) Time 在当前时间基础添加/减少日期

package main

import (
	"fmt"
	"time"
)

func main() {
	var t = time.Now()
	fmt.Println(t)
	fmt.Println(t.Add(24 * time.Hour))
	fmt.Println(t.AddDate(0, 1, 0))
	fmt.Println(t.Add(-24 * time.Hour))
	fmt.Println(t.AddDate(0, -1, 0))
}
9、Sleep

func Sleep(d Duration) 沉睡指定时间

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println(time.Now())
	time.Sleep(3 * time.Second)
	fmt.Println(time.Now())
}
10、NewTimer

func NewTimer(d Duration) *Timer 创建一个定时器,到达指定时间激活一次,timer.C为内部的无缓冲通道

package main

import (
	"fmt"
	"time"
)

func main() {
	var timer = time.NewTimer(5 * time.Second)
	//go func() {
	//	<-timer.C
	//	fmt.Println("这是5秒后啦")
	//}()
	//time.Sleep(10 * time.Second)
	func() {
		<-timer.C
		fmt.Println("这是5秒后啦")
	}()
}
package main

import (
	"fmt"
	"time"
)

func main() {
	var timer = time.NewTimer(5 * time.Second)
	go func() {
		<-timer.C
		fmt.Println("这是5秒后啦")
	}()
	time.Sleep(time.Second)

	// 取消定时器
	stop := timer.Stop()
	if stop {
		fmt.Println("计时器已停止!")
	}
	time.Sleep(10 * time.Second)
}
11、NewTicker

间隔指定时间激活一次

func NewTicker(d Duration) *Ticker 创建一个心跳,间隔指定时间激活一次,ticker.C为内部的无缓冲通道

package main

import (
	"fmt"
	"time"
)

func main() {
	var ticker = time.NewTicker(2 * time.Second)
	defer ticker.Stop()

	var flag = make(chan bool)
	go func() {
		time.Sleep(10 * time.Second)
		flag <- true
	}()

	for {
		select {
		case <-flag:
			fmt.Println("结束程序!")
			return
		case <-ticker.C:
			fmt.Println("定时器激活!")
		}
	}
}

15.5、path

1、Join

func Join(elem ...string) string 拼接路径

package main

import (
	"fmt"
	"path"
)

func main() {
	fmt.Println(path.Join("gostudy", "go.mod"))
}
2、Split

func Split(path string) (dir, file string) 分割路径

package main

import (
	"fmt"
	"path"
)

func main() {
	var p = "/root/GolandProjects/gostudy/go.mod"
	fmt.Println(path.Split(p))
}
3、Dir/Base/

func Dir(path string) string 获取路径的目录部分

func Base(path string) string 获取路径的文件部分

func Ext(path string) string 获取路径的文件扩展名部分

package main

import (
	"fmt"
	"path"
)

func main() {
	var p = "/root/GolandProjects/gostudy/go.mod"
	fmt.Println(path.Dir(p))
    fmt.Println(path.Base(p))
    fmt.Println(path.Ext(p))
}

15.6、os

1、Mkdir/MkdirAll

func Mkdir(name string, perm FileMode) error 创建目录,如父目录不存在则报错

func MkdirAll(path string, perm FileMode) error 创建目录,如父目录不存在则创建

// 注意这里使用的是windows!
package main

import (
	"fmt"
	"os"
)

func main() {
	err := os.Mkdir("aaa", os.ModePerm)
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("make dir success!")

	err1 := os.MkdirAll("aaa\\bbb\\cc", os.ModePerm)
	if err1 != nil {
		fmt.Println(err1)
        return
	}
	fmt.Println("make dir success!")
}
2、ReadDir

func ReadDir(name string) ([]DirEntry, error) 读取文件夹

package main

import (
    "fmt"
    "os"
)

func main() {
    dir, err := os.ReadDir("/Users/xumeng03/Downloads")
    if err != nil {
       fmt.Println(err)
       return
    }
    for _, d := range dir {
       if d.IsDir() {
          fmt.Println(d.Name())
       }
    }
}
3、Create

func Create(name string) (*File, error) 创建文件,如存在则会清空文件

package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.Create("a.txt")
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("create file success!", file)
}
4、Stat

func Stat(name string) (FileInfo, error) 获取文件信息

package main

import (
	"fmt"
	"os"
)

func main() {
	stat, err := os.Stat("go.mod")
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("文件名称:", stat.Name())
	fmt.Println("文件大小:", stat.Size())
	fmt.Println("文件模式:", stat.Mode())
	fmt.Println("文件修改时间:", stat.ModTime())
	fmt.Println("文件是否未目录:", stat.IsDir())
}
5、Open/OpenFile

func Open(name string) (*File, error) 以O_RDONLY打开文件

func OpenFile(name string, flag int, perm FileMode) (*File, error) 以指定模式打开文件

package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.Open("a.txt")
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("open file success!", file)
	err = file.Close()
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("close file success!", file)
  
  // os.O_RDONLY // 只读
  // os.O_WRONLY // 只写
  // os.O_RDWR // 读写
  // os.O_APPEND // 往文件中添建(Append)
  // os.O_CREATE // 如果文件不存在则先创建
  // os.O_TRUNC // 文件打开时裁剪文件
  // os.O_EXCL // 和O_CREATE一起使用,文件不能存在
  // os.O_SYNC // 以同步I/O的方式打开
	file, err = os.OpenFile("a.txt", os.O_WRONLY, os.ModePerm)
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("open file success!", file)
	err = file.Close()
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("close file success!", file)
}
6、Remove/RemoveAll

func Remove(name string) error 移除文件,若为目录且目录下有文件,返回错误

package main

import (
	"fmt"
	"os"
)

func main() {
	err := os.Remove("a.txt")
	if err != nil {
		fmt.Println(err)
        return
	}
	fmt.Println("remove file success!")
}

func RemoveAll(path string) error 强制移除文件,忽略目录下是否有文件,慎用!

package main

import (
	"fmt"
	"os"
)

func main() {
	err1 := os.MkdirAll("aaa\\bbb\\cc", os.ModePerm)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	fmt.Println("make dir success!")

	file, err := os.Create("aaa\\bbb\\cc\\a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("create file success!", file)
	err1 = file.Close()
	if err1 != nil {
		fmt.Println(err1)
		return
	}

	err = os.RemoveAll("aaa\\bbb")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("remove file success!")
}
7、Rename

func Rename(oldpath, newpath string) error 重命名/移动文件

package main

import (
	"fmt"
	"os"
)

func main() {
	err := os.Mkdir("aaa", 0777)
	if err != nil {
		fmt.Println(err)
		return
	}

	_, err = os.Create("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}

	err = os.Rename("a.txt", "aaa/aaa.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
}
8、Chmod

func Chmod(name string, mode FileMode) error 修改文件权限

package main

import (
	"fmt"
	"os"
)

func main() {
	_, err := os.Create("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}

	err = os.Chmod("a.txt", 0777)
	if err != nil {
		fmt.Println(err)
		return
	}
}

func Chown(name string, uid, gid int) error 修改文件所有者

package main

import (
	"fmt"
	"os"
)

func main() {
	_, err := os.Create("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}

	// os.Getuid():用户ID
	// os.Getgid():组ID
	fmt.Println(os.Getuid(), os.Getgid())
	err = os.Chown("a.txt", os.Getuid(), os.Getgid())
	if err != nil {
		fmt.Println(err)
		return
	}
}
9、Read/ReadFile

func (f *File) Read(b []byte) (n int, err error) 读取指定字节,到结尾读取数n=0,err=io.EOF

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	file, err := os.Open("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("open success!", file)

	defer file.Close()

	for {
		var buffer = make([]byte, 5, 5)
		n, err := file.Read(buffer)
		if err == io.EOF {
			break
		}
		fmt.Println(string(buffer[:n]))
	}

	fmt.Println("read end")
}

func ReadFile(name string) ([]byte, error) 读取整个文件内容,只适合小文件!

package main

import (
	"fmt"
	"os"
)

func main() {
  // ioutil.ReadFile
	file, err := os.ReadFile("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(file))
}
10、Write/WriteString

func (f *File) Write(b []byte) (n int, err error) 写入byte数组到文件

package main

import (
	"fmt"
	"os"
)

func main() {
	// 从开头开始写
	//file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
	// 追加内容
	file, err := os.OpenFile("a.txt", os.O_RDWR|os.O_APPEND, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	var b = []byte("hello world!")

	n, err := file.Write(b)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(n)
}

func (f *File) WriteString(s string) (n int, err error) 写入字符串到文件

package main

import (
	"fmt"
	"os"
)

func main() {
	// 从开头开始写
	//file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
	// 追加内容
	file, err := os.OpenFile("a.txt", os.O_RDWR|os.O_APPEND, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	n, err := file.WriteString("hello world!!!")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(n)
}
11、Seek

func (f *File) Seek(offset int64, whence int) (ret int64, err error) 设置光标位置

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	file, err := os.Create("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	n, err := file.WriteString("hello world!")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(n)
	err = file.Close()
	if err != nil {
		fmt.Println(err)
		return
	}
	file, err = os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
	// io.SeekStart:文件开头
	// io.SeekCurrent:当前位置
	// io.SeekEnd:文件结尾
	file.Seek(0, io.SeekCurrent)
	n, err = file.WriteString("I'm xumeng03!")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(n)
}
12、Truncate

func Truncate(name string, size int64) error 裁剪文件

package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	err = file.Truncate(8)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("truncate file success!")
}
13、案例:复制文件
package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	originfile, err := os.Open("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer originfile.Close()

	newfile, err1 := os.Create("b.txt")
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	defer newfile.Close()

	for {
		var b = make([]byte, 1024)
		n, err := originfile.Read(b)
		if err != nil && err != io.EOF {
			fmt.Println(err)
			return
		}
		fmt.Println("read byte:", n)
		write, err1 := newfile.Write(b[:n])
		if err1 != nil {
			fmt.Println(err)
			return
		}
		fmt.Println("write byte:", write)
		if err == io.EOF {
			break
		}
	}
	fmt.Println("copy success!")
}

15.7、io

1、Copy

func Copy(dst Writer, src Reader) (written int64, err error) 复制文件

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	originfile, err := os.Open("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer originfile.Close()

	newfile, err := os.Create("b.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer newfile.Close()

	written, err := io.Copy(newfile, originfile)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(written)
}

15.8、bufio

1、ReadBytes/ReadString

func (b *Reader) ReadBytes(delim byte) ([]byte, error) 逐行读取(bufio包下)

func (b *Reader) ReadString(delim byte) (string, error) 逐行读取(bufio包下)

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

func main() {
	file, err := os.Open("a.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	//reader := bufio.NewReader(file)
	//for {
	//	bytes, err := reader.ReadBytes('\n')
	//	if err != nil && err != io.EOF {
	//		fmt.Println(err)
	//		return
	//	}
	//	fmt.Println(strings.TrimSpace(string(bytes)))
	//	if err == io.EOF {
	//		break
	//	}
	//}
    
	reader := bufio.NewReaderSize(file, 1024)
	for {
		str, err := reader.ReadString('\n')
		if err != nil && err != io.EOF {
			fmt.Println(err)
			return
		}
		fmt.Println(strings.TrimSpace(str))
		if err == io.EOF {
			break
		}
	}
}
2、Write/WriteString

func (b *Writer) Write(p []byte) (nn int, err error) 向文件写入byte数组

func (b *Writer) WriteString(s string) (int, error) 向文件写入字符串

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	//writer := bufio.NewWriter(file)
	//nn, err := writer.Write([]byte("hello world!"))
	//if err != nil {
	//	fmt.Println(err)
	//	return
	//}
	//fmt.Println(nn)

	writer := bufio.NewWriterSize(file, 1024)
	nn, err := writer.WriteString("hello world!!!")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(nn)

	writer.Flush()
}

15.9、ioutil

从Go 1.16版本开始,ioutil包中的一些函数已被标记为不推荐使用,因为这些函数在处理大文件时可能会导致内存泄漏或性能问题。

15.10、runtime

1、GOROOT/GOOS/NumCPU/GOMAXPROCS

func GOROOT() string 获取GOROOT路径

func NumCPU() int 获取内核数

func GOMAXPROCS(n int) int 设置go运行时最大可用CPU数

package main

import (
	"fmt"
	"runtime"
)

func main() {
	// 获取GOROOT路径
	fmt.Println(runtime.GOROOT())
	// 获取系统
	fmt.Println(runtime.GOOS)
	// 获取内核数
	fmt.Println(runtime.NumCPU())
}

func init() {
	// 设置go运行时最大可用CPU数
	runtime.GOMAXPROCS(runtime.NumCPU())
}
2、Gosched/Goexit

func Gosched() 主动让出执行权

package main

import (
	"fmt"
	"runtime"
)

func main() {
	go func() {
		for i := 0; i < 1000; i++ {
			fmt.Println("\tgoroutine1:", i)
		}
	}()
	for i := 0; i < 1000; i++ {
		if i == 100 {
			runtime.Gosched()
		}
		fmt.Println("goroutine0:", i)
	}
}

func Goexit() 结束协程(如有defer函数仍会执行)

package main

import (
	"fmt"
	"runtime"
)

func main() {
	go func() {
		for i := 0; i < 1000; i++ {
			fmt.Println("\tgoroutine1:", i)
			if i == 100 {
				runtime.Goexit()
			}
		}
	}()
	for i := 0; i < 1000; i++ {
		fmt.Println("goroutine0:", i)
	}
}

15.11、sync

1、Add/Wait/Done

func (wg *WaitGroup) Add(delta int) 向同步等待组中添加正增量(需要在调用前增加计数)

func (wg *WaitGroup) Done() 向同步等待组中添加负增量

func (wg *WaitGroup) Wait() 等待同步等待组的计数器归零

package main

import (
	"fmt"
	"sync"
)

var waits = sync.WaitGroup{}

func main() {
	waits.Add(1)
	go iPrint("\tgoroutine1")
	waits.Add(1)
	go iPrint("\tgoroutine2")
	iPrint("主goroutine")
	waits.Wait()
	fmt.Println("全部执行完成!")
}

func iPrint(str string) {
	for i := 0; i <= 50; i++ {
		fmt.Println(str, "打印", i)
	}
	waits.Done()
}
2、Lock/Unlock

互斥锁:同一时间只有一个协程访问资源

当一个goroutine需要访问共享资源时,它会先调用Mutex的Lock方法来获取锁,如果锁已经被其他goroutine获取,则当前goroutine会被阻塞,直到锁被释放。因此,Mutex并不需要指定对谁加锁,它只需要保证同一时间只有一个goroutine可以获取锁即可

func (m *Mutex) Lock() 获取锁

func (m *Mutex) Unlock() 释放锁

package main

import (
	"fmt"
	"sync"
	"time"
)

var l = sync.Mutex{}
var ticket = 10

func main() {
	go iPrint("\tgoroutine1")
	go iPrint("\tgoroutine2")
	iPrint("主goroutine")
}

func iPrint(str string) {
	for i := 0; i <= 10; i++ {
		l.Lock()
		if ticket > 0 {
			time.Sleep(time.Second)
			fmt.Println(str, "买出票:", ticket)
			ticket--
			l.Unlock()
		} else {
			l.Unlock()
			break
		}
	}
}
3、RLock/RUnlock/Lock/Unlock

读写锁:读的时候随便读,写的时候只能等

package main

import (
	"fmt"
	"sync"
	"time"
)

var l = sync.RWMutex{}
var waits = sync.WaitGroup{}

func main() {
	// 多个读操作可以同时进行
	//waits.Add(1)
	//go read("1")
	//waits.Add(1)
	//go read("2")
	//waits.Add(1)
	//go read("3")
	//waits.Wait()
	//fmt.Println("读取完成")

	// 写操作同一时间点只能有一个在进行
	//waits.Add(1)
	//go write("1")
	//waits.Add(1)
	//go write("2")
	//waits.Add(1)
	//go write("3")
	//waits.Wait()
	//fmt.Println("写入完成")
	
	// 读操作可以穿插,但是写操作不可被打断
	waits.Add(1)
	go read("1")
	waits.Add(1)
	go write("2")
	waits.Add(1)
	go read("3")
	waits.Add(1)
	go read("4")
	waits.Wait()
	fmt.Println("写入完成")
}

func read(str string) {
	l.RLock()
	fmt.Println(str, "开始读操作。。。")
	time.Sleep(time.Second)
	fmt.Println(str, "假装是一个读操作。。。")
	fmt.Println(str, "结束读操作。。。")
	l.RUnlock()
	waits.Done()
}

func write(str string) {
	l.Lock()
	fmt.Println(str, "开始写操作。。。")
	time.Sleep(5 * time.Second)
	fmt.Println(str, "假装是一个写操作。。。")
	fmt.Println(str, "结束写操作。。。")
	l.Unlock()
	waits.Done()
}

16、第三方包

Go Mod:Go语言包管理工具

地址:https://pkg.go.dev/

// 模块名称
module gostudy

// go最低版本
go 1.20

// 依赖
require (
	github.com/bytedance/sonic v1.10.2 // indirect
	github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
	github.com/chenzhuoyu/iasm v0.9.0 // indirect
	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
	github.com/gin-contrib/sse v0.1.0 // indirect
	github.com/gin-gonic/gin v1.9.1 // indirect
	github.com/go-playground/locales v0.14.1 // indirect
	github.com/go-playground/universal-translator v0.18.1 // indirect
	github.com/go-playground/validator/v10 v10.15.5 // indirect
	github.com/goccy/go-json v0.10.2 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/klauspost/cpuid/v2 v2.2.5 // indirect
	github.com/leodido/go-urn v1.2.4 // indirect
	github.com/mattn/go-isatty v0.0.20 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/pelletier/go-toml/v2 v2.1.0 // indirect
	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
	github.com/ugorji/go/codec v1.2.11 // indirect
	golang.org/x/arch v0.5.0 // indirect
	golang.org/x/crypto v0.14.0 // indirect
	golang.org/x/net v0.17.0 // indirect
	golang.org/x/sys v0.13.0 // indirect
	golang.org/x/text v0.13.0 // indirect
	google.golang.org/protobuf v1.31.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)

16.1、开启Go Mod

# 启用Go模块支持
go env -w GO111MODULE=on
# 配置Go模块代理GOPROXY
https://mirrors.aliyun.com/goproxy

16.2、Go Mod命令

# 初始化go.mod
go mod init 包名
# 下载包
go get -u github.com/gin-gonic/gin
# 清理未使用依赖包
go mod tidy
# 下载依赖
go mod download
# 更新包
go get -u
# 将依赖下载到项目中
go mod vendor

17、自定义包

  • 只能有一个main包作为程序入口
  • 一个包可以包含多个Go源文件,但是它们必须在同一个目录下,并且属于同一个包(一般与文件夹名保持一致)
  • 以大写字母开头的标识符是可导出的,可以被其他包引用,以小写字母开头的标识符是私有的,只能在当前包内使用
  • 包可以有任意个init函数(没有参数,没有返回值),当包被导入时会先执行init函数
  • init函数调用顺序是同一个文件中按上下顺序,同一包按照文件首字母排序,不同包中按照导入顺序
  • import时用_导入包,并不使用该包中的任何函数、变量、类型,只会执行包中的init函数

17.1、基础使用

// 自定义包
package string

import "fmt"

func Count(arr []int) int {
	return len(arr)
}

func count(arr []int) int {
	return len(arr)
}

func init() {
	fmt.Println("string init......")
}

使用自定义包

package main

// 导入包
import (
	"fmt"
	"golang/utils/string"
)

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

17.2、省略包名

package main

import (
	"fmt"
	// 别名
	. "golang/utils/string"
)

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

17.3、包起别名

package main

import (
	"fmt"
	// 别名
	str "golang/utils/string"
)

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

17.4、_导入

package main

import (
	"fmt"
	// 别名
	_ "golang/utils/string"
)

func main() {
	fmt.Println("main......")
}

17.5、发布自己的包

待补。。。

18、反射

18.1、基本使用

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var f = 3.1415926
	fmt.Println("type:", reflect.TypeOf(f), "value:", reflect.ValueOf(f))
	value := reflect.ValueOf(f)
	fmt.Println("type:", value.Kind())
	fmt.Println("value:", value.Float())
}

18.2、获取/设置对象信息

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var person = Person{"xumeng03", 23}
	get(person)
	set(&person)
	fmt.Println(person)
}

// 反射在设置结构体类型的属性时,只能设置被导出的属性!!!
type Person struct {
	Name string
	Age  int
}

// 反射在获取结构体类型的方法时,只会返回被导出的方法!!!
func (p Person) Hello(str string) {
	fmt.Println(p.Name, ": hello", str, "!")
}

func get(o interface{}) {
	t := reflect.TypeOf(o)
	fmt.Println(t.Name(), t.Kind())
	v := reflect.ValueOf(o)
	fmt.Println(v)

	// 属性
	fmt.Println("属性个数", t.NumField())
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i)
		fmt.Println("属性名:", field.Name, "属性类型:", field.Type, "属性值:", value)
	}

	// 方法
	fmt.Println("方法个数", t.NumMethod())
	for i := 0; i < t.NumMethod(); i++ {
		method := t.Method(i)
		fmt.Println("方法名:", method.Name, "方法类型:", method.Type)
		method.Func.Call([]reflect.Value{reflect.ValueOf(o), reflect.ValueOf("yanmou")})
	}
}

func set(o interface{}) {
	v := reflect.ValueOf(o)
	elem := v.Elem()

	name := elem.FieldByName("Name")
	fmt.Println(v, "是否可以被修改:", name.CanSet())
	name.SetString("xumeng33")

	age := elem.FieldByName("Age")
	fmt.Println(v, "是否可以被修改:", age.CanSet())
	age.SetInt(24)
}

18.3、调用方法

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var person = Person{"xumeng03", 23}
	StructCall(person)
	FuncCall(Hello)
}

// 反射在设置结构体类型的属性时,只能设置被导出的属性!!!
type Person struct {
	Name string
	Age  int
}

// 反射在获取结构体类型的方法时,只会返回被导出的方法!!!
func (p Person) Hello(str string) {
	fmt.Println(p.Name, ": hello", str, "!")
}

func Hello(str string) {
	fmt.Println(str, ": hello!")
}

func StructCall(o interface{}) {
	v := reflect.ValueOf(o)
	fmt.Println(v.Kind(), v.Type())

	// 调用对象的方法
	f := v.MethodByName("Hello")
	f.Call([]reflect.Value{reflect.ValueOf("yanmou")})
}

func FuncCall(f interface{}) {
	v := reflect.ValueOf(f)
	fmt.Println(v.Kind(), v.Type())

	v.Call([]reflect.Value{reflect.ValueOf("xumeng03")})
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

眼眸流转

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值