Fork me on GitHub

go_fiveDay

Go语言-五天学习

image-20210531163821254

介绍、安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
go//package demo_fiveday

// 导入的包 不使用 会报错
// 变量定义了 不使用 也会报错

// 这个包表示是main包 也就是主包 整个程序入口是该文件
package main
// fmt 是内置的包
import "fmt"

// func 关键字 表示定义一个函数 函数名必须叫main
func main () {
fmt.Println("Hello World") // 必须是双引号
}

// 编译 go build 名.go => 名.exe
// 执行 名.exe

// 编译并执行 go run 名.go

image-20210531153934314

go语言命名

25个关键字

image-20210531153949947

关键字用途

image-20210531154003509

数据类型

image-20210531154020127

image-20210531154035168

  • bool 中 true false小写
  • 字符串类型可相加
  • 不同类型不能相加 需转换比如转成int int(a)

语言命名规范

image-20210531154052130

go语言内置类型和函数

内置类型

image-20210531154113843

image-20210531154133478

内置函数

image-20210531154146175

image-20210531154156680

内置接口error

image-20210531154210977

标准输入输出

1
2
3
4
5
6
7
var s1,s2 string
fmt.Scan(&s1, &s2)
fmt.Println("--s1--", s1, "--s2--", s2)
fmt.Scanln(&s1, &s2) // 只能空格 不能回车
fmt.Println("--s1--", s1, "--s2--", s2)
fmt.Scanf("%s", &s1)
fmt.Println("--s1--", s1, "--s2--", s2)

变量

变量是什么

image-20210531154223605

1、变量必须先定义在使用

2、变量不能被重复定义

3、首字母大写 共有 首字母小写 私有

声明单个变量

  1. 基本定义:var a int = 10;
  2. 类型推导: var a = 10
  3. 简便写法: a:= 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 变量声明
// 第一种方式
var a int = 10; // var 关键字,表示声明一个变量,a是变量名 ,int 变量类型 = 变量值
fmt.Println(a);

// 第二种方式 类型推导 不用指定变量类型 自动推导变量类型
var b = 20;
fmt.Println(b);

var c = "lvqing"
fmt.Println(c)

// 第三种方式
d:= 30
e:= "lvqing007"
fmt.Println(d)
fmt.Println(e)

声明多个变量

1
2
3
4
5
6
7
8
9
10
11
12
// 声明多个变量
var f, g int = 40,50
fmt.Println(f,g)

var h,i,j = 60, "lvqing008", "lvqing009"
fmt.Println(h)
fmt.Println(i,j)

m:= "lvqing110"
n:= 007
// m, n := "lvqing110", 007
fmt.Println(m,n)

常量

关键字: const

定义后 不能改变其值

1
2
3
4
5
//常量定义
const x = "lvq"
const y = 12;

fmt.Println(x, y)

函数

函数定义

func 函数名(函数参数名 类型 , 参数名 类型) 返回值类型{

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
函数:
1、没有位置和关键字一说,都是按位置传参
*/

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

// 传参
func test01(a int, b int){
fmt.Println(a + b)
}

// 返回值
func test02(a int, b int) int {
fmt.Println(a + b)

return a+ b
}

//多个返回值,用括号括起来
func test03(a int, b string) (int, string) {
return a, b
}

// 可变长参数
func test04(a ... int){
fmt.Println(a)
}

// 命名返回值
func test05(a int, b int)(c,d int){ // 或者 c int,d int
c = a
d = b

return // 可写return c,d
}

//空白符 舍弃一个返回值
func test06(a int, b int)(c,d int){
c = a
d = b

return
}

匿名函数

没有名字的函数

1
2
3
4
5
6
7
8
9
10
11
// 匿名函数,没有名字的函数,定义在函数内部

a:= func(a, b, c int){
fmt.Println(a,b,c)
}
a(2,3,4)

// 匿名函数其实真正的用 只用一次 以后不会执行了
func(){
fmt.Println("-------------------")
}()

闭包函数

闭包:定义在函数内部 对外层作用域有引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
1、闭包函数使用外部作用域的变量,其实是个引用
*/
x:=10
fmt.Println("10的地址----",&x)
f:= closure(x)
fmt.Println(f(1))



func closure(x int) func(int) int {
fmt.Printf("%p\n", &x)
return func(y int) int {
fmt.Printf("%p\n",&x)
return x+y
}
}

可变长参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 可变长参数	
func_test(3, 1,2,5,3,0,6,9,8,22,55,33)
fmt.Println("*********传切片**********")
// 传切片不可以 打散了传进去 为 n...
n := []int{88, 66, 7, 3, 99}
func_test(99, n...)
func func_test(num int, nums ...int){
for k,v := range nums{
fmt.Println("key:",k, " value:",v)
if num == v{
fmt.Println("已找到num, key为", k, "num为", num)
}
}
}

if-else

1
2
3
4
5
6
7
8
9
 // if-else  注意: i1>i2 后面不能换行	 
i1,i2 := 2,3
if i1>i2{
fmt.Println("i1小于i2")
}else if i1 == i2 {
fmt.Println("i1等于i2")
}else {
fmt.Println("i1大于i2")
}

循环

没有while循环,只有for循环

image-20210531163857269

1
2
3
4
5
6
7
8
9
	 //循环	 
for i := 0; i < 10; i++{
fmt.Println(i)
}
var f1 = 0
for ; f1 < 3; f1++{
fmt.Println("--------------")
fmt.Println(f1)
}
1
2
3
4
5
//用for模拟while  会死循环
var t1= truefor t1{
fmt.Println("t1")
t1 = false
}

switch-case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var s1 = 4
switch s1 {
case 1, 2:
fmt.Println("1")
case 3:
fmt.Println("3")
case 4:
fmt.Println("4")
case 5:
fmt.Println("5")
default:
fmt.Println("6")
}
//无条件
var s2 = 4
switch { // 表达式被忽略
case s2 >= 0 && s2 <= 3:
fmt.Println("s2---1")
case s2 >= 4:
fmt.Println("s2---2")
default:
fmt.Println("s2---3")
}

fallthrough

穿透下面那层 不论符合不符合 无条件执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   var s1 = 4
switch s1 {
case 1, 2:
fmt.Println("1")
case 3:
fmt.Println("3")
case 4:
fmt.Println("4")
fallthrough
case 5:
fmt.Println("5")
default:
fmt.Println("6")
}

数组

image-20210531163912425

数组声明

1、数组有长度 有类型

2、int类型空值 0 字符串空值 “”

3、不能直接扩容 只能重新定义一个新的把数据copy过来

4、类型相同 长度不同的数组 不能直接赋值 比如: b = a

5、长度 len

6、循环两种方式: 一种for循环 另一种 range

7、给某个值赋初始值 var b7[7] int = [7]int{3:88, 2:77}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var b1[3] int	
fmt.Println(b1)
var b2[3] string
fmt.Println(b2)
var b3[3]
string b3[0] = "lv" b3[1] = "qing"
fmt.Println(b3)
// 定义并赋初值
var b4[3] string = [3]string{"ll","qq","ii"}
fmt.Println(b4)
b5 := [...]int{1,2,3,4,5,6} // 虽然写的... 但是长度还是后面固定的 (小样 ...还想骗人 我是不会上当的)
fmt.Println(b5)
//数组是值类型
b6:= [3]int{4,5,6}
test07(b6)
fmt.Println(b6)
fmt.Println(len(b6))
// 遍历
for key,val := range b6{
// 用一个是索引 两个是索引 、值
fmt.Println(key)
fmt.Println(val)
}
// 给数组某个值赋初始值
var b7[7] int = [7]int{3:88, 2:77}
fmt.Println(b7)
// 数组函数
func test07(a [3]int){
a[1] = 66
fmt.Println(a)
}

range

1
2
3
4
5
6
7
8
9
10
//数组是值类型	
b6:= [3]int{4,5,6}
test07(b6)
fmt.Println(b6)
fmt.Println(len(b6))
// 遍历
for key,val := range b6{ // 用一个是索引 两个是索引 、值
fmt.Println(key)
fmt.Println(val)
}

多维数组

1
2
3
4
// 多维数组	
var b8[2][3]
int = [2][3]int { {1,2,3}, {4,5,6}, }
fmt.Println(b8)

切片

可以动态往里面添加值

可以自动扩容

1、[]int 切片类型

2、切片底层依附于数组,改值 数组也会变化

3、切片动态的追加值 超过数组的len 数组不会变化 不会在依附于此时的数组 会重新定义一个长度为原来数组的两倍的新数组
切片会依赖于新数组 在改值 原来旧数组不会变 变化的是新数组

定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
1、[]int 切片类型
2、切片底层依附于数组,改值 数组也会变化
3、切片动态的追加值 超过数组的len
数组不会变化 不会在依附于此时的数组 会重新定义一个长度为原来数组的两倍的新数组
切片会依赖于新数组 在改值 原来旧数组不会变 变化的是新数组
*/
var b[] int // 切片类型
var c[3] int = [3]int {} // 数组
fmt.Println(b)
fmt.Println(c)
//定义并初始化
var c2[3] int = [3]int {1,2,3} // 数组
fmt.Println(c2)
// 第一种方式: make初始化
var b2[] int = make([]int, 3) // 切片
fmt.Println(b2)
// 第二种方式: 通过数组切片
b3 := c2[0:len(c2)] // 前闭后开
b3[0] = 100 // 切片改值 数组也会变
b3 = append(b3, 800) // 切片追加值
b3[1] = 999 // 超过长度 不会在依附于数组了

fmt.Println(b3)
fmt.Println(c2)
fmt.Println(len(b3), cap(b3)) // 查看切片长度和底层数组长度

copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// copy
fmt.Println("-------copy------")
var b4 = make([]int,3)
b4[0] = 8
b4[1] = 6
b4[2] = 4
fmt.Println(b4)

b5:= make([]int, 6)
fmt.Println(b5)

copy(b5, b4)
fmt.Println(b4, len(b4), cap(b4))
fmt.Println(b5, len(b5), cap(b5))
b5[0] = 111
b5[1] = 222
b5[2] = 333
fmt.Println("------------")
fmt.Println(b4, len(b4), cap(b4))
fmt.Println(b5, len(b5), cap(b5))

copy(b4, b5)
fmt.Println("------------")
fmt.Println(b4, len(b4), cap(b4))
fmt.Println(b5, len(b5), cap(b5))

切片当做参数传给函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//切片当做参数传给函数  函数修改 切片会被修改
fmt.Println("-----func-------")
b6:= make([]int, 3)
b6[0] = 1
b6[1] = 2
b6[2] = 3
fmt.Println(b6)
test_slice(b6)
fmt.Println(b6)

func test_slice(b[] int){
b[0] = 999

fmt.Println(b)
}

map

1、key-value 对

2、Map是引用类型

3、判断map相等不能用== ==只能用来判断map是否为nil

4、map是无序的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*		
1、key-value 对
2、Map是引用类型
3、判断map相等不能用== ==只能用来判断map是否为nil
4、map是无序的
*/
fmt.Println("-----map-------")
// 定义
var m1 map[int]string
// 空值是nil格式
//m1[1] = "QQQQ" 为空的不能直接赋值 有问题
fmt.Println(m1)
// 定义并初始化 - int key类型,string value类型
// 第一种
// var m2 map[int]string = map[int]string{1:"ll", 2:"vv"}
// 第二种
var m2 map[int]string = make (map[int]string)
m2[1] = "ll"
m2[2] = "vv"
m2[3] = "qq"
fmt.Println(m2)
// 取值
fmt.Println(m2[3])
// 取值不存在返回空
fmt.Println(m2[2])
// 删除某个元素
delete(m2, 1)
// 传的是key
fmt.Println(m2)
fmt.Println(len(m2))
// map当参数传递
test_map(m2)
fmt.Println(m2)
// 相等性
m3:= map[int]string{1: "XXXX", 2: "YYYYY"}
fmt.Println(m3)
// 复杂map
var m4 map[int]map[int]string = make(map[int]map[int]string)
if m4[1] == nil{
m4[1] = make(map[int]string)
}
m4[1][1] = "LLLLLLLLLLLL"
m4[1][2] = "VVVVVVVVVVVV"
m4[1][3] = "QQQQQQQQQQQQ"
fmt.Println(m4) // 这只是m4[1] m4[2] m4[3]都没有 要循环
for mk,mv := range m4{
fmt.Println(mk)
fmt.Println(mv)
}
func test_map(m map[int]string){
m[1] = "XXXXXX"
m[2] = "YYYYYY"
}

指针

1、符号 & 表示取地址

2、符号 * 表示通过地址取值

3、指针不支持运算 不支持增加、减少

4、数组类型指针可以直接当做数组来修改,赋值

5、切片类型指针 如要修改切片,需要反解回来 再修改

6、指向数组的指针

7、指针数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 指针
/*
1、符号 & 表示取地址
2、符号 * 表示通过地址取值
3、指针不支持运算 不支持增加、减少
4、数组类型指针可以直接当做数组来修改,赋值
5、切片类型指针 如要修改切片,需要反解回来 再修改
6、指向数组的指针
7、指针数组
*/
// 定义
fmt.Println("-----port-------")
p1:= 123
var p2 *int = &p1
fmt.Println(p2)
fmt.Println(*p2)
// 传递指针类型数组
p3:= [3]int{1,2,3}
fmt.Println(p3)
test_port(&p3)
fmt.Println(p3)

p4 := 123456
p5 := &p4
p6 := &p5
p7 := &p6
fmt.Println(*p7) // p6的地址
fmt.Println(*(*(*p7))) // 值

// 切片类型指针
p8:= []int{2,3,4,5}
fmt.Println(p8)
test_SP(&p8)
fmt.Println(p8)

// 指向数组的指针
var p9 = [...]int{99:1}
fmt.Println(p9)

var p10 *[100]int = &p9
fmt.Println(p10)

// 指针数组
p11 := 11
p12 := 12
var p13 [2]*int = [...]*int{&p11, &p12}
fmt.Println(p13)
fmt.Printf("%T", p13) // 查看类型

func test_port(p *[3]int){
(*p)[0]= 999
p[1] = 888 // 数组类型指针可以直接当做数组来修改,赋值
fmt.Println(p)
fmt.Println(*p)
}

func test_SP(sp *[]int){
fmt.Println(*sp)
(*sp)[0] = 666 // 切片类型指针不能直接赋值 需要反解
fmt.Println(sp)
}

Defer

image-20210531163925622

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func defer_Test(){
defer fmt.Println("我最后打印11111")
defer fmt.Println("我最后打印22222")
fmt.Println("我先打印111111")
fmt.Println("我先打印222222")

for i:=0;i<3;i++{
defer fmt.Println("i=",i)
}
fmt.Println("-------------------------")

for j:=0;j<3;j++{
defer func(){ // 匿名函数-引用
fmt.Println("j=",j)
}()
}
}

Panic

主动抛出异常

Recover

恢复程序

一般写在defer里面 写外面不执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// panic recover
func p1(){
fmt.Println("-------p1--------")
}
func p2(){
defer func() {
// 恢复程序 recover
//recover()
// 出现异常之后不执行 从p2之后执行
//err:= recover()
// err 为空时 表示没有异常
//if err!=nil{
// fmt.Println("ERR",err)
//}
if err2:=recover();
err2!=nil{
fmt.Println("err2",err2)
} }()
fmt.Println("-------p2--------")
panic("出现异常")
fmt.Println("--------p4---------")}
func p3(){
fmt.Println("-------p3--------")
}

小练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 测试练习	
fmt.Println("----------测试练习--------------")
var test01 = [4]func(){}
for i:= 0; i< 4; i++{
defer fmt.Println("defer看i= ", i)
defer func() {
fmt.Println("匿名函数看i= ", i)
}()
test01[i] = func() {
fmt.Println("test01看i= ", i)
}
}
for _,v := range test01{
fmt.Println("----v----", v)
v()
}

文件

读文件

1、普通读文件 ioutil 一次性读出来 不需要手动关闭 内部自己关闭了

2、分片读文件 每次读自定义的个数 os

3、按行读文件 os

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
1、普通读文件 ioutil 一次性读出来 不需要手动关闭 内部自己关闭了
2、分片读文件 每次读自定义的个数
3、按行读文件

*/
// 普通读文件
f_ioutil, err01 := ioutil.ReadFile("file01.txt")
if err01 != nil{
fmt.Println("打开文件失败")
return
}
fmt.Println("----f_ioutil----", f_ioutil)
fmt.Println("----string(f_ioutil)---------", string(f_ioutil))

// 分片、按行读文件
f_os,err02 := os.Open("file01.txt")
if err02 != nil{
fmt.Println("打开文件失败")
return
}

defer func() {
f_os.Close()
fmt.Println("---文件关闭了----")
}()
// 分片读文件 用NewReader
//fmt.Println("-----分片读文件 用NewReader------")
//r:= bufio.NewReader(f_os) // 前面 Open 打开不能读
//b:= make([]byte, 8) // 定义一个切片 读8个
//for{
// _,err := r.Read(b)
// if err!=nil{
// break
// }
// fmt.Println("----string(b)----", string(b))
//}

// 按行读文件 用NewScanner
fmt.Println("-----按行读文件 用NewScanner-----")
s:= bufio.NewScanner(f_os)
for s.Scan(){
fmt.Println( s.Text())
}

写文件

1、按字节写入文件

2、按字符串写入文件

3、追加文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//写入文件
fmt.Println("---------写入文件------------")
f_c,err03 := os.Create("file02.txt")
if err03!=nil{
fmt.Println("创建文件失败")
return
}

defer f_c.Close()

//按字符串按字符串写入文件
fmt.Println("---------按字符串写入文件------------")
l,err04 := f_c.WriteString("我增加了一行字符串")
if err04!=nil{
fmt.Println("写文件失败")
f_c.Close()
}
fmt.Println(l, "success")

// 按字节写文件
fmt.Println("--------按字节写入文件--------")
d2:=[]byte{104, 101, 108, 109}
n2,_:= f_c.Write(d2)

fmt.Println(n2, "success")

// 追加文件
fmt.Println("---------追加文件------------")
f_ofile,_:= os.OpenFile("file02.txt", os.O_APPEND,0644)
newLine := "File handing is easy"
_,_ = fmt.Fprintln(f_ofile,newLine)

fmt.Println( "success")

结构体

image-20210531163938962

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 结构体定义 : type 名 struct{}
type Person struct {
name string
age int
}

// 结构体的嵌套
type man struct {
sex string
person Person
}


/*
1、结构体定义 : type 名 struct{} 定义在外部
2、匿名结构体 定义在内部
3、结构体的嵌套
4、
*/
var p1 Person = Person{
name: "lv qing",
age: 18,
}
p2:= Person{

}
p2.age=17
fmt.Println(p1.name)
fmt.Println(p2.age)
fmt.Println(p1)

// 匿名结构体
ss:= struct {
name string
age int
}{name:"lvq"}
ss.age=16
fmt.Println(ss)

// 结构体的嵌套
p:=man{}
p.sex = "man"
p.person.name = "liu"
p.person.age = 17

p4:=man{"man", Person{"heng", 16}}

fmt.Println(p)
fmt.Println(p4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import (
//"demo_fiveday/demo0510"
"fmt"
)

type Dog struct {
string
pro string
}

type Cat struct {
string
pro string
}

type Animal struct {
string
int
pro string
Dog
}

func main(){

fmt.Println("--------开始导入包-----没有弄出来 不会--")
//demo0510.Import_test()

//匿名字段
fmt.Println("-----------匿名字段-------------")
//a := Animal{"dog", 2}
//fmt.Println(a.string)
//fmt.Println(a.int)

// 匿名字段一般用于嵌套结构
//a := Animal{"dog", 2, Dog{"man", "wangwangwang"}}
//fmt.Println(a.Dog)
//fmt.Println(a.pro) // 字段提升 直接可以用到嵌套里面的属性

// 嵌套结构中有重复的字段
a:= Animal{"Animal", 2, "都会叫", Dog{"小狗", "wangwangwang"}}
fmt.Println(a)
fmt.Println(a.pro)
fmt.Println(a.Dog.pro)

// 结构体的比较
d := Dog{"Dog", "wangwangwang"}
d1 := d
//c := Cat{"Cat", "miaomiaomiao"}

fmt.Println(d1 == d)
//fmt.Println(d == c) // 不能比较
}

方法

方法其实就是函数,在 func 这个关键字和方法名中间加了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器可以在放大的内部访问的。

1、基本使用

2、指针接收器和值接受器

3、函数使用指针接收器

4、自定义类型加方法

​ 函数传参数时,有自动类型转换

​ 不同类型不能直接相比较

1
2
3
4
5
6
7
8
9
10
// 定义 -- 非结构体
func (d myInt) add(b myInt) myInt{
return d + b
}
// 定义 -- 结构体 -- 值接受器
func (b Dog) getName() string{
b.string = "BigDog"
fmt.Println("-方法-", b)
return b.string
}

指针接收器、值接收器

值接收器是值的copy 拷贝的结构体代价过于昂贵

指针接收器 耗费的空间很小 以后做的都用指针接收器

image-20210531154242032

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 定义  -- 结构体  -- 值接受器
func (b Dog) getName() string{
b.string = "BigDog"
fmt.Println("-方法-", b)
return b.string
}
// 指针接收器
func (c *Dog) getPro(){
fmt.Println("---指针接收器-*c--", (*c).pro)
fmt.Println("---指针接收器-c--", c.pro)
}
// 这个叫函数
func getName(b Dog) string{
b.string = "Litter Litter Dog"
fmt.Println("-函数-", b)
return b.string
}
func getPro(b *Dog) {
fmt.Println("-函数指针-", b.pro)
}

接口

1、定义

2、空接口(匿名接口)interface{}

3、类型断言

4、接口的嵌入结构

5、空接口值为nil

image-20210531154301370

协成(goroutin)

并发:立即处理多个任务的能力,单位时间内可以干多少的事 串串执行

并行:同时处理多个任务

image-20210531154344359

1
2
3
4
5
6
7
8
9
10
fmt.Println("---------协成-----------")

go goroutin()
fmt.Println("---------come on--------------")
time.Sleep(2*time.Second) // 睡两秒等等


func goroutin() {
fmt.Println("------go go go-----------")
}

通信(channel)

image-20210531184339430

image-20210531190239742

image-20210531190259174

select

mutex

反射

image-20210601163618707

image-20210601163939665

image-20210601164026862

image-20210601164253085

image-20210601164528565

总结

代码-0428

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//package demo_fiveday
/**
导入的包 不使用 会报错
变量定义了 不使用 也会报错
编译 go build 名.go => 名.exe
执行 名.exe
**/


// 这个包表示是main包 也就是主包 整个程序入口是该文件
package main
// fmt 是内置的包
import "fmt"

// func 关键字 表示定义一个函数 函数名必须叫main
func main () {
//fmt.Println("Hello World") // 必须是双引号

// 变量声明
/*
1、变量必须先定义在使用
2、变量不能被重复定义
*/
// 第一种方式
var a int = 10 // var 关键字,表示声明一个变量,a是变量名 ,int 变量类型 = 变量值
fmt.Println(a)

// 第二种方式 类型推导 不用指定变量类型 自动推导变量类型
var b = 20
fmt.Println(b)

var c = "lvqing"
fmt.Println(c)

// 第三种方式
d := 30
e := "lvqing007"
fmt.Println(d)
fmt.Println(e)

// 声明多个变量
var f, g int = 40, 50
fmt.Println(f, g)

var h, i, j = 60, "lvqing008", "lvqing009"
fmt.Println(h)
fmt.Println(i, j)

m := "lvqing110"
n := 007
fmt.Println(m, n)

//常量定义
const x = "lvq"
const y = 12;

fmt.Println(x, y)

// 函数测试
test()
test01(10, 20) // 传参
test02(10, 20) // 返回值
var l, q = test03(10, "多个返回值") //多个返回值,用括号括起来
fmt.Println(l, q)

test04(1, 2, 3, 4, 5, 6) // 可变长参数 这是一个数组类型
w1, w2 := test05(10, 20)
fmt.Println(w1, w2)

w3, _ := test05(10, 20)
fmt.Println(w3) // 但是_不能打印

// if-else 注意: i1>i2 后面不能换行
i1, i2 := 2, 3
if i1 > i2 {
fmt.Println("i1大于i2")
} else if i1 == i2 {
fmt.Println("i1等于i2")
} else {
fmt.Println("i1小于i2")
}

//循环
for i := 0; i < 3; i++ {
fmt.Println(i)
}

var f1 = 0
for ; f1 < 3; f1++ {
fmt.Println("--------------")
fmt.Println(f1)
}

//用for模拟while 会死循环
var t1 = true
for t1 {
fmt.Println("t1")
t1 = false
}

//switch-case
var s1 = 4
switch s1 {
case 1, 2:
fmt.Println("1")
case 3:
fmt.Println("3")
case 4:
fmt.Println("4")
fallthrough
case 5:
fmt.Println("5")
default:
fmt.Println("6")
}
//无条件
var s2 = 4
switch { // 表达式被忽略
case s2 >= 0 && s2 <= 3:
fmt.Println("s2---1")
case s2 >= 4:
fmt.Println("s2---2")
default:
fmt.Println("s2---3")
}

// 数组
/*
1、数组有长度 有类型
2、int类型空值 0 字符串空值 ""
3、不能直接扩容 只能重新定义一个新的把数据copy过来
4、类型相同 长度不同的数组 不能直接赋值 比如: b = a
5、长度 len
6、循环两种方式: 一种for循环 另一种 range
*/
var b1[3] int
fmt.Println(b1)

var b2[3] string
fmt.Println(b2)

var b3[3] string
b3[0] = "lv"
b3[1] = "qing"
fmt.Println(b3)

// 定义并赋初值
var b4[3] string = [3]string{"ll","qq","ii"}
fmt.Println(b4)
b5 := [...]int{1,2,3,4,5,6} // 虽然写的... 但是长度还是后面固定的
fmt.Println(b5)

//数组是值类型
b6:= [3]int{4,5,6}
test07(b6)
fmt.Println(b6)
fmt.Println(len(b6))

// 遍历
for key,val := range b6{ // 用一个是索引 两个是索引 、值
fmt.Println(key)
fmt.Println(val)
}

// 给数组某个值赋初始值
var b7[7] int = [7]int {3:88, 2:77}
fmt.Println(b7)

// 多维数组
var b8[2][3] int = [2][3]int {
{1,2,3},
{4,5,6},
}
fmt.Println(b8)

}

/*
函数:
1、没有位置和关键字一说,都是按位置传参
*/

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

// 传参
func test01(a int, b int){
fmt.Println(a + b)
}

// 返回值
func test02(a int, b int) int {
fmt.Println(a + b)

return a+ b
}

//多个返回值,用括号括起来
func test03(a int, b string) (int, string) {
return a, b
}

// 可变长参数
func test04(a ... int){
fmt.Println(a)
}

// 命名返回值
func test05(a int, b int)(c,d int){ // 或者 c int,d int
c = a
d = b

return // 可写return c,d
}

//空白符 舍弃一个返回值
func test06(a int, b int)(c,d int){
c = a
d = b

return
}

// 数组函数
func test07(a [3]int){
a[1] = 66
fmt.Println(a)

}

运行结果-0428

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
10
20
lvqing
30
lvqing007
40 50
60
lvqing008 lvqing009
lvqing110 7
lvq 12
test
30
30
10 多个返回值
[1 2 3 4 5 6]
10 20
10
i1小于i2
0
1
2
--------------
0
--------------
1
--------------
2
t1
4
5
s2---2
[0 0 0]
[ ]
[lv qing ]
[ll qq ii]
[1 2 3 4 5 6]
[4 66 6]
[4 5 6]
3
0
4
1
5
2
6
[0 0 77 88 0 0 0]
[[1 2 3] [4 5 6]]

代码-0429

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package main

import (
"fmt"
)

func main(){

// 冒泡排序
var a = [10]int {4,5,6,7,23,90,39,456,56,432}
fmt.Println("排序前",a)
for i:= 0; i<len(a); i++{
for j := i+1; j < len(a); j++{
if a[i] < a[j]{
tmp:= a[i]
a[i]= a[j]
a[j] = tmp
}
}
}
fmt.Println("排序后",a)

// 切片
/*
1、[]int 切片类型
2、切片底层依附于数组,改值 数组也会变化
3、切片动态的追加值 超过数组的len
数组不会变化 不会在依附于此时的数组 会重新定义一个长度为原来数组的两倍的新数组
切片会依赖于新数组 在改值 原来旧数组不会变 变化的是新数组
*/
var b[] int // 切片类型
var c[3] int = [3]int {} // 数组
fmt.Println(b)
fmt.Println(c)
//定义并初始化
var c2[3] int = [3]int {1,2,3} // 数组
fmt.Println(c2)
// 第一种方式: make初始化
var b2[] int = make([]int, 3) // 切片
fmt.Println(b2)
// 第二种方式: 通过数组切片
b3 := c2[0:len(c2)] // 前闭后开
b3[0] = 100 // 切片改值 数组也会变
b3 = append(b3, 800) // 切片追加值
b3[1] = 999 // 超过长度 不会在依附于数组了

fmt.Println(b3)
fmt.Println(c2)
fmt.Println(len(b3), cap(b3)) // 查看切片长度和底层数组长度

// copy
fmt.Println("-------copy------")
var b4 = make([]int,3)
b4[0] = 8
b4[1] = 6
b4[2] = 4
fmt.Println(b4)

b5:= make([]int, 6)
fmt.Println(b5)

copy(b5, b4)
fmt.Println(b4, len(b4), cap(b4))
fmt.Println(b5, len(b5), cap(b5))
b5[0] = 111
b5[1] = 222
b5[2] = 333
fmt.Println("------------")
fmt.Println(b4, len(b4), cap(b4))
fmt.Println(b5, len(b5), cap(b5))

copy(b4, b5)
fmt.Println("------------")
fmt.Println(b4, len(b4), cap(b4))
fmt.Println(b5, len(b5), cap(b5))

//切片当做参数传给函数 函数修改 切片会被修改
fmt.Println("-----func-------")
b6:= make([]int, 3)
b6[0] = 1
b6[1] = 2
b6[2] = 3
fmt.Println(b6)
test_slice(b6)
fmt.Println(b6)

// map
/*
1、key-value 对
2、Map是引用类型
3、判断map相等不能用== ==只能用来判断map是否为nil
4、map是无序的
*/
fmt.Println("-----map-------")
// 定义
var m1 map[int]string // 空值是nil格式
//m1[1] = "QQQQ" 为空的不能直接赋值 有问题
fmt.Println(m1)
// 定义并初始化 - int key类型,string value类型
var m2 map[int]string = make (map[int]string)
m2[1] = "ll"
m2[2] = "vv"
m2[3] = "qq"
fmt.Println(m2)
// 取值
fmt.Println(m2[3]) // 取值不存在返回空
fmt.Println(m2[2])
// 删除某个元素
delete(m2, 1) // 传的是key
fmt.Println(m2)
fmt.Println(len(m2))
// map当参数传递
test_map(m2)
fmt.Println(m2)
// 相等性
m3:= map[int]string{1: "XXXX", 2: "YYYYY"}
fmt.Println(m3)

// 复杂map
var m4 map[int]map[int]string = make(map[int]map[int]string)
if m4[1] == nil{
m4[1] = make(map[int]string)
}
m4[1][1] = "LLLLLLLLLLLL"
m4[1][2] = "VVVVVVVVVVVV"
m4[1][3] = "QQQQQQQQQQQQ"
fmt.Println(m4) // 这只是m4[1] m4[2] m4[3]都没有 要循环
for mk,mv := range m4{
fmt.Println(mk)
fmt.Println(mv)
}

// 指针
/*
1、符号 & 表示取地址
2、符号 * 表示通过地址取值
3、指针不支持运算 不支持增加、减少
4、数组类型指针可以直接当做数组来修改,赋值
5、切片类型指针 如要修改切片,需要反解回来 再修改
6、指向数组的指针
7、指针数组
*/
// 定义
fmt.Println("-----port-------")
p1:= 123
var p2 *int = &p1
fmt.Println(p2)
fmt.Println(*p2)
// 传递指针类型数组
p3:= [3]int{1,2,3}
fmt.Println(p3)
test_port(&p3)
fmt.Println(p3)

p4 := 123456
p5 := &p4
p6 := &p5
p7 := &p6
fmt.Println(*p7) // p6的地址
fmt.Println(*(*(*p7))) // 值

// 切片类型指针
p8:= []int{2,3,4,5}
fmt.Println(p8)
test_SP(&p8)
fmt.Println(p8)

// 指向数组的指针
var p9 = [...]int{99:1}
fmt.Println(p9)

var p10 *[100]int = &p9
fmt.Println(p10)

// 指针数组
p11 := 11
p12 := 12
var p13 [2]*int = [...]*int{&p11, &p12}
fmt.Println(p13)
fmt.Printf("%T", p13) // 查看类型
}

func test_slice(b[] int){
b[0] = 999

fmt.Println(b)
}

func test_map(m map[int]string){
m[1] = "XXXXXX"
m[2] = "YYYYYY"
}

func test_port(p *[3]int){
(*p)[0]= 999
p[1] = 888 // 数组类型指针可以直接当做数组来修改,赋值
fmt.Println(p)
fmt.Println(*p)
}

func test_SP(sp *[]int){
fmt.Println(*sp)
(*sp)[0] = 666 // 切片类型指针不能直接赋值 需要反解
fmt.Println(sp)
}

运行结果-0429

1
2
3
4
5
6
7
排序前 [4 5 6 7 23 90 39 456 56 432]
排序后 [456 432 90 56 39 23 7 6 5 4]
[][0 0 0][1 2 3][0 0 0][100 999 3 800][100 2 3]4 6
-------copy------[8 6 4][0 0 0 0 0 0][8 6 4] 3 3[8 6 4 0 0 0] 6 6------------[8 6 4] 3 3[111 222 333 0 0 0] 6 6------------[111 222 333] 3 3[111 222 333 0 0 0] 6 6-----func-------[1 2 3][999 2 3][999 2 3]-----map-------map[]map[1:ll 2:vv 3:qq]qqvvmap[2:vv 3:qq]2map[1:XXXXXX 2:YYYYYY 3:qq]map[1:XXXX 2:YYYYY]map[1:map[1:LLLLLLLLLLLL 2:VVVVVVVVVVVV 3:QQQQQQQQQQQQ]]1map[1:LLLLLLLLLLLL 2:VVVVVVVVVVVV 3:QQQQQQQQQQQQ]-----port-------0xc00000a2e8123[1 2 3]&[999 888 3][999 888 3][999 888 3]0xc000006030123456[2 3 4 5][2 3 4 5]&[666 3 4 5][666 3 4 5][0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]&[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1][0xc00000a6b8 0xc00000a6c0][2]*int


----ao hu 乱序了 不想改了 凑凑合合看吧 你是最棒的----

代码-0507

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
package main

import (
"bufio"
"fmt"
"io/ioutil"
"os"
)

// 结构体定义 : type 名 struct{}
type Person struct {
name string
age int
}

// 结构体的嵌套
type man struct {
sex string
person Person
}

func main(){
// 匿名函数和闭包
// 匿名函数,没有名字的函数,定义在函数内部

a:= func(a, b, c int){
fmt.Println(a,b,c)
}
a(2,3,4)

// 匿名函数其实真正的用 只用一次 以后不会执行了
func(){
fmt.Println("--------匿名函数-----------")
}()

/*
1、闭包函数使用外部作用域的变量,其实是个引用
*/
x:=10
fmt.Println("----10的地址----",&x)
f:= closure(x)
fmt.Println(f(1))

// defer
defer_Test()
// panic 和 recover
fmt.Println("---------panic 和 recover------------")
p1()
p2()
p3()

// 可变长参数
func_test(3, 1,2,5,3,0,6,9,8,22,55,33)
fmt.Println("*********传切片**********")
// 传切片不可以 打散了传进去 为 n...
n := []int{88, 66, 7, 3, 99}
func_test(99, n...)

//// 测试练习
//fmt.Println("----------测试练习--------------")
//var test01 = [4]func(){}
//for i:= 0; i< 4; i++{
// defer fmt.Println("defer看i= ", i)
//
// defer func() {
// fmt.Println("匿名函数看i= ", i)
// }()
//
// test01[i] = func() {
// fmt.Println("test01看i= ", i)
// }
//}
//
//for _,v := range test01{
// fmt.Println("----v----", v)
// v()
//}

// 文件
fmt.Println("-------------文件练习--------------")
/*
1、普通读文件 ioutil 一次性读出来 不需要手动关闭 内部自己关闭了
2、分片读文件 每次读自定义的个数
3、按行读文件

1、按字节写入文件
2、按字符串写入文件
3、追加文件

*/
// 普通读文件
f_ioutil, err01 := ioutil.ReadFile("file01.txt")
if err01 != nil{
fmt.Println("打开文件失败")
return
}
fmt.Println("----f_ioutil----", f_ioutil)
fmt.Println("----string(f_ioutil)---------", string(f_ioutil))

// 分片、按行读文件
f_os,err02 := os.Open("file01.txt")
if err02 != nil{
fmt.Println("打开文件失败")
return
}

defer func() {
f_os.Close()
//fmt.Println("---文件关闭了----")
}()
// 分片读文件 用NewReader
//fmt.Println("-----分片读文件 用NewReader------")
//r:= bufio.NewReader(f_os) // 前面 Open 打开不能读
//b:= make([]byte, 8) // 定义一个切片 读8个
//for{
// _,err := r.Read(b)
// if err!=nil{
// break
// }
// fmt.Println("----string(b)----", string(b))
//}

// 按行读文件 用NewScanner
fmt.Println("-----按行读文件 用NewScanner-----")
s:= bufio.NewScanner(f_os)
for s.Scan(){
fmt.Println( s.Text())
}


//写入文件
fmt.Println("---------写入文件------------")
f_c,err03 := os.Create("file02.txt")
if err03!=nil{
fmt.Println("创建文件失败")
return
}

defer f_c.Close()

//按字符串按字符串写入文件
fmt.Println("---------按字符串写入文件------------")
l,err04 := f_c.WriteString("我增加了一行字符串")
if err04!=nil{
fmt.Println("写文件失败")
f_c.Close()
}
fmt.Println(l, "success")

// 按字节写文件
fmt.Println("--------按字节写入文件--------")
d2:=[]byte{104, 101, 108, 109}
n2,_:= f_c.Write(d2)

fmt.Println(n2, "success")

// 追加文件
fmt.Println("---------追加文件------------")
f_ofile,_:= os.OpenFile("file02.txt", os.O_APPEND,0644)
newLine := "File handing is easy"
_,_ = fmt.Fprintln(f_ofile,newLine)

fmt.Println( "success")

//// 标准输入输出
//var s1,s2 string
//fmt.Scan(&s1, &s2)
//fmt.Println("--s1--", s1, "--s2--", s2)
//fmt.Scanln(&s1, &s2) // 只能空格 不能回车
//fmt.Println("--s1--", s1, "--s2--", s2)
//fmt.Scanf("%s", &s1)
//fmt.Println("--s1--", s1, "--s2--", s2)

// 结构体
fmt.Println("--------结构体-----------")
/*
1、结构体定义 : type 名 struct{} 定义在外部
2、匿名结构体 定义在内部
3、结构体的嵌套
4、
*/
var p1 Person = Person{
name: "lv qing",
age: 18,
}
p2:= Person{

}
p2.age=17
fmt.Println(p1.name)
fmt.Println(p2.age)
fmt.Println(p1)

// 匿名结构体
ss:= struct {
name string
age int
}{name:"lvq"}
ss.age=16
fmt.Println(ss)

// 结构体的嵌套
p:=man{}
p.sex = "man"
p.person.name = "liu"
p.person.age = 17

p4:=man{"man", Person{"heng", 16}}

fmt.Println(p)
fmt.Println(p4)
}

func closure(x int) func(int) int {
fmt.Printf("%p\n", &x)
return func(y int) int {
fmt.Printf("%p\n",&x)
return x+y
}
}

func defer_Test(){
defer fmt.Println("我最后打印11111")
defer fmt.Println("我最后打印22222")
fmt.Println("我先打印111111")
fmt.Println("我先打印222222")

for i:=0;i<3;i++{
defer fmt.Println("i=",i)
}
fmt.Println("------------defer测试-------------")

for j:=0;j<3;j++{
defer func(){ // 匿名函数-引用
fmt.Println("j=",j)
}()
}
}

// panic recover
func p1(){
fmt.Println("-------p1--------")
}
func p2(){

defer func() {
// 恢复程序 recover
//recover() // 出现异常之后不执行 从p2之后执行

//err:= recover() // err 为空时 表示没有异常
//if err!=nil{
// fmt.Println("ERR",err)
//}
if err2:=recover();err2!=nil{
fmt.Println("err2",err2)
}

}()

fmt.Println("-------p2--------")
panic("出现异常")
fmt.Println("--------p4---------")
}
func p3(){
fmt.Println("-------p3--------")
}

func func_test(num int, nums ...int){
for k,v := range nums{
fmt.Println("key:",k, " value:",v)
if num == v{
fmt.Println("已找到num, key为", k, "num为", num)
}
}
}

运行结果-0507

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
2 3 4
--------匿名函数-----------
----10的地址---- 0xc00000a0a8
0xc00000a0c0
0xc00000a0c0
11
我先打印111111
我先打印222222
------------defer测试-------------
j= 3
j= 3
j= 3
i= 2
i= 1
i= 0
我最后打印22222
我最后打印11111
---------panicrecover------------
-------p1--------
-------p2--------
err2 出现异常
-------p3--------
key: 0 value: 1
key: 1 value: 2
key: 2 value: 5
key: 3 value: 3
已找到num, key为 3 num为 3
key: 4 value: 0
key: 5 value: 6
key: 6 value: 9
key: 7 value: 8
key: 8 value: 22
key: 9 value: 55
key: 10 value: 33
*********传切片**********
key: 0 value: 88
key: 1 value: 66
key: 2 value: 7
key: 3 value: 3
key: 4 value: 99
已找到num, key为 4 num为 99
-------------文件练习--------------
----f_ioutil---- [230 130 168 229 165 189 32 228 184 150 231 149 140 13 10 229 184 166 231 157 128 228 184 150 231 149 140 229 135 186 229 142 187 231 156 139 231 156 139 13 10 45 45 45 45 45 45 45 45 45 45 45 45 45 13 10 42 42 42 42 42 42 42 42 42 42 42 42 42 13 10 48 48 48 48 48 48 48 48 48 48 48 48 48 13 10 108 108 108 108 108 108 108 108 108 108 108 108 108 13 10 118 118 118 118 118 118 118 118 118 118 118 118 118]
----string(f_ioutil)--------- 您好 世界
带着世界出去看看
-------------
*************
0000000000000
lllllllllllll
vvvvvvvvvvvvv
-----按行读文件 用NewScanner-----
您好 世界
带着世界出去看看
-------------
*************
0000000000000
lllllllllllll
vvvvvvvvvvvvv
---------写入文件------------
---------按字符串写入文件------------
27 success
--------按字节写入文件--------
4 success
---------追加文件------------
success
--------结构体-----------
lv qing
17
{lv qing 18}
{lvq 16}
{man {liu 17}}
{man {heng 16}}

代码-0510

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main

import (
//"demo_fiveday/demo0510"
"fmt"
)

type Dog struct {
string
pro string
}

type Cat struct {
string
pro string
}

type Animal struct {
string
int
pro string
Dog
}

// 非结构体
type myInt int

func main(){

fmt.Println("--------开始导入包-----没有弄出来 不会--")
//demo0510.Import_test()

//匿名字段
fmt.Println("-----------匿名字段-------------")
//a := Animal{"dog", 2}
//fmt.Println(a.string)
//fmt.Println(a.int)

// 匿名字段一般用于嵌套结构
//a := Animal{"dog", 2, Dog{"man", "wangwangwang"}}
//fmt.Println(a.Dog)
//fmt.Println(a.pro) // 字段提升 直接可以用到嵌套里面的属性

// 嵌套结构中有重复的字段
a:= Animal{"Animal", 2, "都会叫", Dog{"小狗", "wangwangwang"}}
fmt.Println(a)
fmt.Println(a.pro)
fmt.Println(a.Dog.pro)

// 结构体的比较
d := Dog{"Dog", "wangwangwang"}
d1 := d
//c := Cat{"Cat", "miaomiaomiao"}

fmt.Println(d1 == d)
//fmt.Println(d == c) // 不能比较


// 方法的使用
fmt.Println("------------方法的使用------------")
b:= Dog{"LitterDog", "wangwangwang"}
c:= b.getName()
c1:= getName(b)
fmt.Println("--方法--", c)
fmt.Println("--函数--",c1)

(&b).getPro()
b.getPro()
// 函数上使用指针类型
getPro(&b)

// 非结构的方法
var a1 myInt = 10
num :=a1.add(6)
fmt.Println(num)
}


// 方法
/*****
1、基本使用
2、指针接收器和值接受器
3、函数使用指针接收器
4、自定义类型加方法
函数传参数时,有自动类型转换
不同类型不能直接相比较
*****/
// 定义 -- 结构体 -- 值接受器
func (b Dog) getName() string{
b.string = "BigDog"
fmt.Println("-方法-", b)

return b.string
}

// 这个叫函数
func getName(b Dog) string{
b.string = "Litter Litter Dog"
fmt.Println("-函数-", b)
return b.string
}

func getPro(b *Dog) {
fmt.Println("-函数指针-", b.pro)
}

// 指针接收器
func (c *Dog) getPro(){
fmt.Println("---指针接收器-*c--", (*c).pro)
fmt.Println("---指针接收器-c--", c.pro)
}

// 定义 -- 非结构体
func (d myInt) add(b myInt) myInt{
return d + b
}

运行结果-0510

1
-------开始导入包-----没有弄出来 不会-------------匿名字段-------------{Animal 2 都会叫 {小狗 wangwangwang}}都会叫wangwangwangtrue------------方法的使用-------------方法- {BigDog wangwangwang}-函数- {Litter Litter Dog wangwangwang}--方法-- BigDog--函数-- Litter Litter Dog---指针接收器-*c-- wangwangwang---指针接收器-c-- wangwangwang---指针接收器-*c-- wangwangwang---指针接收器-c-- wangwangwang-函数指针- wangwangwang16

代码-0519

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main

import "fmt"


// 接口
/***
1、定义
2、空接口(匿名接口)interface{}
3、类型断言
4、接口的嵌入结构
***/
// 1、定义接口
type Usb interface {
Connect()
Close()
}

type Phone struct {
name string
}

type Computer struct {
name string
}

func (a Phone) Connect(){
fmt.Println("-----连接了-----", a.name)
}

func (a Phone) Close(){
fmt.Println("----关闭了-----", a.name)
}

func (a Computer) Connect(){
fmt.Println("-----连接了-----", a.name)
}

func (a Computer) Close(){
fmt.Println("----关闭了-----", a.name)
}



func main() {
// 接口
fmt.Println("-------接口--------")
phone := Phone{name:"iphonexmax"}
phone.Connect()
phone.Close()

computer := Computer{"联想电脑"}
computer.Connect()
computer.Close()


testc(computer)
testp(phone)
fmt.Println("-------test---------")
testu(computer)
testu(phone)

//匿名空接口
fmt.Println("-------匿名空接口---------")
test2(1)
test2("hhahah")

// 类型断言
fmt.Println("-------类型断言---------")
testType(phone)
testType(computer)
}

// 现在写一个连接电脑处理事情的 关闭电脑的方法
func testc(c Computer){
c.Connect()
fmt.Println("-----电脑处理一下事情-----")
c.Close()
}

// 现在写一个连接手机处理事情的 关闭手机的方法
func testp(p Phone){
p.Connect()
fmt.Println("-----手机处理一下事情-----")
p.Close()
}

//这样太麻烦了 写一个usb类型 都可以传
func testu(u Usb){
u.Connect()
fmt.Println("-----通用方法处理事情--------")
u.Close()
}

// 2、空接口 interface{} -- 所有的类型都可以传
func test2(a interface{}){
fmt.Println("---匿名空接口---", a)
}

//类型断言
func testType(u Usb){
// 第一种书写方式
phone,ok := u.(Phone) // 类型判断 变量u是不是Phone类型
if ok{
fmt.Println(phone.name)
}
// 第二种书写方式
if computer,ok := u.(Computer); ok{
fmt.Println(computer.name)
}

// 用switch进行类型判断
switch v:=u.(type) {
case Computer:
fmt.Println("-我是电脑--",v.name)
case Phone:
fmt.Println("-我是手机--",v.name)
default:
fmt.Println("-不知道啥类型")
}
}

运行结果-0519

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-------接口--------
-----连接了----- iphonexmax
----关闭了----- iphonexmax
-----连接了----- 联想电脑
----关闭了----- 联想电脑
-----连接了----- 联想电脑
-----电脑处理一下事情-----
----关闭了----- 联想电脑
-----连接了----- iphonexmax
-----手机处理一下事情-----
----关闭了----- iphonexmax
-------test---------
-----连接了----- 联想电脑
-----通用方法处理事情--------
----关闭了----- 联想电脑
-----连接了----- iphonexmax
-----通用方法处理事情--------
----关闭了----- iphonexmax
-------匿名空接口---------
---匿名空接口--- 1
---匿名空接口--- hhahah
-------类型断言---------
iphonexmax
-我是手机-- iphonexmax
联想电脑
-我是电脑-- 联想电脑

代码-0531

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main

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

type Usb interface {
Connect()
// 接口嵌套使用
Use2
}

type Use2 interface {
Close()
GetName() string
}

type Phone struct {
name string
}


func (a Phone) Connect(){
fmt.Println("-----连接了-----", a.name)
}

func (a Phone) Close(){
fmt.Println("----关闭了-----", a.name)
}

func (a Phone) GetName() string{
fmt.Println("----名字----")

return a.name
}

func main(){
phone:= Phone{"iphoneX"}
// 把phone转成了Usb接口类型 注意: phone没有实现usb的全部接口 是不能转成usb的
// phone 能转成usb usb 不能转成phone 只能向下转
var usb = Usb(phone)

fmt.Println("--usb--",usb.GetName())

// 空接口
var nty interface { }

fmt.Println("---------调用空接口-----------")
fmt.Println(nty == nil) // true

var n *int = nil
nty = n
fmt.Println(nty == nil) // false n不为nil a存的是指向nil的指针,不为空,所以不是nil
fmt.Println(n == nil)

// 协成
fmt.Println("---------协成-----------")
//go goroutin()
fmt.Println("---------come on--------------")
time.Sleep(2*time.Second) // 睡两秒等等

// 通道
fmt.Println("---------通道-----------")
/***
1、 定义 make创建 close关闭
2、 引用类型
3、 等着线程执行完 在执行 不需要sleep
4、 通过for range不断的取值
*/
var c = make(chan bool)
// 往信道中放值
//c<-3
go goroutin(c)
c2:=<-c
fmt.Println("-----", c2)

var c3= make(chan bool)
go func() {
fmt.Println("------c3-----")
c3<-true

close(c3)
}()
// 用for循环的时候一定要用close关闭通道
for v :=range c3{
fmt.Println("---v---",v)
}

// 有缓冲通道 无缓冲通道
fmt.Println("------有缓冲通道 无缓冲通道-----")
var c4 = make(chan int, 10) // 通道里面可以放三个值 有缓冲(放满了才回取运行) 不写默认是0 无缓冲(放一个就开始运行)

for i:= 0; i< 10; i++{
go goroutin_c(c4, i) // 开了10个线程计算0加到10000
}

for i := 0; i< 10; i++{
//<- c4 // 取出来
count := 0
num := <-c4
count = count + num

fmt.Println("---count---", count)
}

// WaitGroup实现同步,有三个方法: Add,Done,Wait
fmt.Println("---WaitGroup实现同步---")
wg:= sync.WaitGroup{} // 定义一个WaitGroup
// 增加10个任务
wg.Add(10)
for i := 0; i < 10; i++{
// 传入wg的引用
go goroutin_wg(&wg, i)
}

wg.Wait() // 等待所有的任务完成


}

func goroutin(g chan bool) {
fmt.Println("------go go go-----------")
g<-true
}

func goroutin_c (g chan int, index int) {
a := 1
for i := 0; i < 10000; i++{
a++
}
fmt.Println(index, a)
g <- a
}

func goroutin_wg(wg *sync.WaitGroup, index int){
a:= 1
for i:= 0; i< 10000; i++{
a++
}
fmt.Println("----", index, a)
wg.Done()
}

运行结果-0531

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
----名字----
--usb-- iphoneX
---------调用空接口-----------
true
false
true
---------协成-----------
---------come on--------------
---------通道-----------
------go go go-----------
----- true
------c3-----
---v--- true
------有缓冲通道 无缓冲通道-----
0 10001
---count--- 10001
4 10001
9 10001
5 10001
---count--- 10001
---count--- 10001
---count--- 10001
6 10001
8 10001
---count--- 10001
2 10001
---count--- 10001
3 10001
---count--- 10001
---count--- 10001
7 10001
1 10001
---count--- 10001
---count--- 10001
---WaitGroup实现同步---
---- 0 10001
---- 2 10001
---- 1 10001
---- 4 10001
---- 3 10001
---- 6 10001
---- 9 10001
---- 5 10001
---- 7 10001
---- 8 10001