# go_study **Repository Path**: chenzhuo_cy/go_study ## Basic Information - **Project Name**: go_study - **Description**: go_study - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2019-03-30 - **Last Updated**: 2024-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # go_study #### gitHub学习地址 : https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/directory.md #### 介绍 go_study 一 学习框架--go 开发实战 : 1 初始Go语言 2 基础类型 3 运算符 4 流程控制 5 函数 6 工程管理 7 复合类型 8 面向对象编程 9 异常处理 10 文本文件处理 11 并发编程 12 网络编程 二 编码随笔 82 http : 网络通信 a 服务端,客户端,To B(企业~使用+管理),To C(用户~体验+使用) b 移动版,网页版(PC)~~终端类别,用户类别~~C端与B端 c 实际爬虫主要4大步骤 : 1)明确目标[网站,搜索目标] 2)爬[网站内容爬下来] 3)取[去掉没用数据] 4)处理数据[存储] 81 webnet : 网络传输 a 网络通信条件 : 1) 网卡 , MAC地址 ARP ==> 通过IP找MAC地址 2) 逻辑地址,ip地址 ==> 确定哪个网段的哪个电脑接收 3) 端口 ==> 为了确定哪个程序接收[1个程序只能绑定1个端口] b Socket,Unix--“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作 c Socket就是Unix模式的一个实现,网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符 d Socket常用类型: 流式Socket (Socket Stream ,面向连接TCP) & 数据Socket (Socket Dgram,服务应用UDP) e 简单版并发服务器 , 服务端--windows 客户端测试 cmd端多出两个字符 '\r\n'[-2],git/linux--多出1个 80 web : 网络 a 从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则。 b 为减少协议设计的复杂性,大多数网络模型均采用分层的方式来组织,每一层都靠下一层支持 c 每一层利用下一层提供的服务来为上一层提供服务,本层服务的实现细节对上层屏蔽。 d TCP/IP协议[组] : 链路层[ARP,RARP,硬件接口] , 网络层[ICMP,IP,IGMP] , 传输层[TCP,UDP] , 应用层[FTP,Telnet,TFTP,NFS]; 网卡[网卡标识==>网卡地址==>物理地址==>MAC地址] e TCP-网络分层 : 链路层[物理层,数据链路层](设备间) , 网络层[网络层](主机间) , 传输层[传输层](进程间) , 应用层[回话层,表示层,应用层](应用程序数据交互),只用链路层,直找mac地址,会导致广播风暴 f ARP:通过IP定位MAC地址,新增加的网络层引入了新的地址==>IP地址,区域广播 g 传输层: 源端口,目的端口,应用层按照约定好的格式,取出最有效的数据 73 select : 定时器&监听 a Timer是一个定时器,代表未来的一个单一事件,它提供一个channel,在将来的那个时间那个channel提供了一个时间值 b timer延时实现: 1)time.NewTimer(), 2)time.Sleep(2 * time.Second), 3)<-time.After(2 * time.Second) c Ticker--定时触发计时器,以(interval)往channel发送事件,timer-channel在时间间隔从中读取事件,执行操作 d 通过select可以监听channel上的数据流动,与switch语言非常类似,选择新块,每个选择条件由case语句来描述。 e switch语句可选择的条件任意一致性相比, select限制较多,最大限制就是每个case语句里必须是一个IO操作 [单向channel] 72 channel : 通道/管道 管理 a goroutine运行在相同的地址空间,因此访问共享内存必须做好同步,奉行通过通信来共享内存,而不是共享内存来通信 b 主进程步骤中channel的接收,等于在结束前加了把锁,既保证协程可执行,协程也可发送channel数据保证主进程不阻塞 c 有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道 d close(channel)无法再发送数据 ,chan[双向,默认],range 来迭代不断操作channel e 单向{chan<-[只写不读],<-chan[只读不写]},单向无法转为双向,而双向可隐式转单向 [eg : 应用: 生产者 & 消费者] 71 goroutine : 协程 a 并行 : 多个指令在多个处理器上同时运行, 并发 : 同一时刻只有一条指令执行,但多个进程指令被快速地轮询执行, 使得在宏观上具有多个进程同时执行的效果,原理上,将时间分成若干段,多个进程快速交替执行,这就是并发 b 并行是两个队列同时使用两台咖啡机,并发是两个队列交替使用一台咖啡机 c Go--21世纪C语言[简单,并行程序设计],Go从语言层面上支持了并行,提供了自动垃圾回收机制 d Go语言为并发编程而内置的上层API基于CSP[顺序通讯进程],避免显式锁,简化并发编写[安全通道接收/发送数据] e 新建一个协程 ==> 新建一个任务 , 主协程退出了,其它子协程也要跟着退出 f Gosched ==>让出时间片,先让别的协议执行,它执行完,再回来执行此协程 g runtime.Goexit() ==> 终止所在的协程,多任务线程,会出现公共资源的竞争 64 file_simple : 文件常规读写 a [默认已经打开,可直接使用]os.Stdout.Close() //关闭后,无法输出, os.Stdin.Close() //关闭后,无法输入 b writeFile : os.Create(path) & defer file.Close() & buffer = fmt.Sprintf(...) & file.WriteString(buffer) c readFile : os.Open(path) & defer file.Close() & buffer := make([]byte, 1024*2) & fn, ferr := file.Read(buffer) & string(buffer[:fn]) d readFileLine : os.Open(path) & defer file.Close() & stash := bufio.NewReader(file) buffer, linErr := stash.ReadBytes('\n') && fmt.Printf(" %d ", string(buffer)) e 整行读取 : 新建缓存区,把内容整体放入缓存区中 ,遍历循环,遇到'\n'结束读取,但要注意'\n' f file-常用引用 : import ("fmt","io","os" ,"bufio") g 文件拷贝:代码健壮!srcFile.Read(dataBuffer) & destFile.Write(dataBuffer[:data]) 63 json_struct : json结构体解析 a JSON (JavaScript Object Notation)是一种比XML更轻量级的数据交换格式,适合跨平台的数据交互 b json.Marshal(object) , json.MarshalIndent(object, "", "") [格式化] c JSON官方网站:http://www.json.org/ , 在线格式化:http://www.json.cn/ d `json` 解析 : -不输出 , 二次编码转小写[`json:"subjects"], `json:",string"`[原样输出] e json.Unmarshal()反解析, json反转换为type / map [类型断言&&range] 62 string_regex : 字符串&正则表达式 a Contains[包含] , Join[组合] , Index[索引] , Repeat[] , import "strings" 加入引用 b Replace[替换] , Spilt[切分] , Trim[去空格] , fields[] c Append , Format , Parse [追加,格式化,转化],import "strconv" 加入引用 d 正则: 1)解释规则, 它会解析正则表达式,如果成功返回解释器,2)根据规则提取关键信息 e 正则: 解释正则表达式, +匹配前一个字符的1次或多次, ``--原生字符串 f 正则表达式是一种进行模式匹配和文本操纵的复杂而又强大的工具,regexp.MustCompile() g 按照语法规则,随需构造出的匹配模式就能够从原始文本中筛选出所需字符组合。 h \d\.\d+ : +(匹配前一个一次或多次),\d(转义为数字),\.(字符'.') i .* : 爬虫网页所需内容,只需要中间的内容,(?s:(.*?)) : 去除换行,内容不重复 61 exception : 异常 a error[原则/程序错误] fmt.Errorf() , errors.New()实现, 函数返回值后可加一error回调 b panic[致命错误,崩溃] 显式调用panic函数,会导致程序中断,最常见的就是数组越界 c recovers :“拦截”运行时panic的内建函数,从运行时panic的状态中恢复并重新获得流程控制权 54 interface : 接口 a 接口--只有声明,没有实现,由别的类型(自定义类型)实现 b 调用同一函数,不同表现,多态,多种形态,创建一个切片,并据此观察 c 超集可以转换为子集,反过来不可以,向上转型ok,向下转型会异常err d 空接口万能类型,保存任意类型的值,类型查询,类型断言 53 methodHigh : 方法高级 a 继承重名--就近原则:先找本作用域的方法,找不到再用继承的方法,若想使用匿名重名方法,需显示调用 b 方法继承,方法值,方法表达式等都是方法的高级用法,方法表达式先隐藏接收者,后再显示传递 52 methodFunc : 对象方法 a 面向过程&面向方法区别 :后者给某个类型绑定一个函数,调用格式: 变量名.函数(所需参数) b 接收者就是传递了一个参数,方法是面向对象另外一种表现形式,带有接收者的函数叫方法 c 只要接收者类型不一样,该方法就算同名,也是不同方法,不会出现重复定义函数的错误 d 在Go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法 e receiver 类型可任意命名,可以是 T 或 *T。基类型 T 不能是接口或指针,不支持重载 f 结构体变量是一个指针变量,它能够调用很多方法,这些方法就是一个集合,简称方法集。 g 用实例实例[value]和指针[pointer]调用方法(含匿名字段)不受方法集约束, h 编译器编总是能根据(value/pointer)查找全部方法,并自动转换 receiver 实参。 51 anonymous : 对象匿名 a struct对象初始化时,可指定成员,未指定的自动赋值为0/'', %+v, 显示更详细 b 针对同名情况,默认规则,如果能在本作用域找到,就操作此成员,否则,操作继承成员,或者显示操作 c +v : 带key , v : 不带key 45 struct : 结构体 a 结构体struct,顺序初始化,每个成员必须初始化;指定成员初始化,没有初始化的成员,会自动赋值为0 b 操作成员,需要使用点(.)运算符,通过指针合法操作成员,也可以使用点(.)运算符,new申请新struct c 同类型的2个结构体变量可以相互赋值, 【可见性--当多个源文件处于同级目录,可引用,否则方法要大写】 44 map : 字典 a map可以通过make创建,甚至还可以指定长度,键值唯一,同时无序,无法控制返回顺序 b 对已初始化的赋值,如果已经存在的key值,修改内容,追加时,map底层自动扩容,和append类似 c 使用 range 判断map中的key值是否存在,eg : value, ok := m[0] {key-->value , key-->flag} 43 slice : 切片 a 切片(slice)来弥补数组副本的不足,不是数组或数组指针,它通过内部指针和相关属性引用数组片段 b 数组[]里面的长度时是固定的, len和cap永远都是一样的,而切片[]里面为空,或者为...,可以不固定 c 切片初始化 : 自动推导类型,借助make函数(切片类型, 长度, [容量]),eg : make([]int, 5) d append函数向 slice 尾部添加数据,一旦超过原底层数组容量,通常以2倍容量重新分配底层数组,并复制原来的数据 e copy 在两个 slice 间复制数据,复制度以 len 小的为准,可指向同一底层数组,引用传递,且会出现覆盖 42 array : 数组 a 数组,同一个类型的集合,操作数组,通过下标, 从0开始,到len()-1 b 定义数组时,指定的数组元素个数必须是常量,不对称元素,叫下标,可常量/变量 c 数组声明定义同时赋值,即数组初始化;部分未初始化的元素,自动赋值为0;还可指定初始化 d 数组维度由初始化数组时[]的个数决定,所以遍历使用时,应该循环相应次数 f 数组比较,只支持 == 或 !=, 比较是不是每一个元素都一样,同时数组类型要一样 g import "math/rand" "time" ,rand.Int())--随机很大的数,限制在100内的数, rand.Intn(100) h 数组做函数参数,值传递,形参的数组是实参数组的复制品,不是引用 41 pointer : 指针 a 指针的每个变量有2层含义:变量的内存,变量的地址,声明即定义,特殊的声明 b 变量的地址--指针类型 *int 保存int的地址, **int 保存 *int 地址 c pointer--不要操作没有合法指向的内存,当为nil时,可以使用new()初始化 d 函数变量--变量本身传递,值传递,非指针执行完毕后并不会回带已改变的值 33 funcHigh : 函数高级 a defer--延迟,一般main函数结束前调用,只能出现在函数或方法的内部 b 多个defer语句,它们会以LIFO(后进先出)的顺序执行,即便出错,也会执行[栈] c 若执行前defer语句时已传入参数,即便后面变量发生改变,执行结果依旧是传入时的值 d 获取命令行参数 : os.Args [光标停留在Args上,再按F2,即可查看],接收用户传递的参数 e 作用域:已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围 f 不同作用域,允许定义同名变量,使用变量的原则,就近原则 g 点操作,别名操作,忽略操作 , import ("fmt" "os")最为常用 32 funccBetter : 函数深入 a 函数调用流程 : 先调用后返回,先进后出;而函数递归即函数调用自己本身 b 函数递归--函数必须要有终止条件--传统,递归,其他方式实现累加求和 c 函数也是一种数据类型, 通过type给一个函数类型起名--->多态 d 闭包~~一个函数“捕获”和它同一作用域的其它常量和变量,并以引用方式捕获外部变量 e 闭包~~当闭包被调用时,程序闭包能够使用这些常量或者变量 f 闭包~~闭包不关心捕获的变/常量是否超过作用域,所以只要闭包还在使用,量就会存在 g 匿名函数~~没有函数名称,函数字面量 31 funcNormal : 函数入门 a 无参无返回值函数的调用: 函数名(),有参无返回值函数的定义, 普通参数列表 b 定义函数时, ()中叫形参,参数传递,只能由实参传递给形参, 单向传递 c 不定参数--(...) ,注意不要引起歧义,一定(只能)放在形参中的最后一个参数 d 当与普通形参一起使用时,注意:固定参数一定要传参,不定参数根据需求传递 f args[:2]---args[0]~args[2](不包括数字args[2]),args[2:]--从args[2]开始(包括本身) g 单个返回值 : test3() (result int) 21 process -- 流程控制 a if , else if支持1个初始化语句, 初始化语句和判断条件以分号分隔 b switch后面写的是变量本身,保留了break关键字,跳出switch语言, 不写,默认就包含 c switch-fallthrough : 不跳出switch语句,后面的无条件执行 d for 初始化条件 ; 判断条件 ; 条件变化 e range : 迭代,结合切片,for,匿名参数使用最为广泛 f sleep , for , continue , break && goto End 11 operator -- 运算符 a 算数,关系,逻辑,位,赋值,其他等运算符,注意运算符优先级 b 一元运算符拥有最高的优先级,二元运算符的运算方向均是从左至右 06 dataDict -- 类型别名 a bool类型不能转换为int , 0就是假,非0就是真,同时整型也不能转换为bool b 字符类型本质上就是整型,把ch的值取出来后,转成int再给t赋值 c 数据类型别名 eg : type bigint int64 , 此时 var a bigint 等价于 var a int64 05 format -- 格式化输出 a %T --变量所属类型 , %d --整型 , %s --字符串 b %c --字符 , %f --浮点型, %v --自动匹配[最常用] c Scan --键盘录入[&--占位] 04 dataType -- 数据类型 a bool--布尔型 : %T b float64--浮点型 : float64存储小数比float32更准确 c byte--字符型 : %c以字符方式打印,%d以整型方式打印,'\'以反斜杠开头的字符是转义字符 d string--字符串类型 : 内建函数,len()可以测字符串的长度,有多少个字符 e string与byte区别 : 字符,往往都只有一个字符,转义字符除外'\n',字符串有1个或多个字符组成,隐藏了一个结束符,'\0' f complex128 : 复数【实部+虚部】,通过内建函数,取实部[real()]和虚部[imag()] 03 constant 常量 a 程序运行期间,不可以改变的量,常量声明需要const b 程序运行期间,可以改变的量, 变量声明需要var c 枚举iota,iota给常量赋值使用,每个一行,自动累加1,遇到const,重置为0 d 枚举iota,一行只写一个iota,当变量/常量与iota出现在同一行,则值都一样 02 normal 命名 ,变量,语法等 a 自动推导,同一个变量名只能使用一次,用于初始化那次 b println , print关系,多重复制与匿名变量 c 匿名变量配合函数返回值使用,才有优势 01 world main同文件夹下只可以有一个 go-command: run , build 00 hello go的第一行代码 三 课堂随笔 4 Go是为多核和并发而生 并行是两个队列同时使用两台咖啡机 并发是两个队列交替使用一台咖啡机 3 文件 设备文件 : 屏幕(标准输入设备) [fmt.println()==>向输出设备写] , 键盘(标准输出设备) [fmt.Scan()==>从输入设备读取内容] 磁盘文件 : 放在存储设备上的文件 [二进制文件(乱码),文本文件] 2 Go--面向对象--形象解释 : a 继承 : 继承来自拖拉机,实现了扫地接口 b 封装 : 无需知道如何工作,开动即可 c 多态 : 平时扫地,天热当风扇 d 重用 : 没有额外动力,重复利用了发动机能量 e 多线程 :多个扫把同时工作 f 低耦合 :扫把改为拖把,无需改动 1 数据类型(同类数据) -- 告诉编译器变量参数应该以多大内存存储 四 书籍参考 : https://books.studygolang.com/gopl-zh/