
Golang语言的学习
文章平均质量分 68
分享我对Golang语言的学习
林林林ZEYU
坚持
展开
-
999-Golang的并发编程(2)
channelchannel是Go语言在语言级别提供的goroutine间的通信方式。我们可以使用channel在两个或多个goroutine之间传递消息。channel是进程内的通信方式,因此通过channel传递对象的过程和调用函数时的参数传递行为比较一致,比如也可以传递指针等。如果需要跨进程通信,我们建议用分布式系统的方法来解决,比如使用Socket或者HTTP等通信协议。Go语言对于网络方面也有非常完善的支持。channel是类型相关的。也就是说,一个channel只能传递一种类型的值,这个类原创 2022-02-24 13:12:34 · 540 阅读 · 0 评论 -
998-Golang的并发编程(1)
在“序”中,我们已经描述过Go语言中最重要的一个特性,那就是go关键字。优雅的并发编程范式,完善的并发支持,出色的并发性能是Go语言区别于其他语言的一大特色。使用Go语言开发服务器程序时,就需要对它的并发机制有深入的了解。并发基础回到在Windows和Linux出现之前的古老年代,程序员在开发程序时并没有并发的概念,因为命令式程序设计语言是以串行为基础的,程序会顺序执行每一条指令,整个程序只有一个执行上下文,即一个调用栈,一个堆。并发则意味着程序在运行时有多个执行上下文,对应着多个调用栈。我们知道每一原创 2022-02-24 11:48:47 · 315 阅读 · 0 评论 -
997-Golang的面向对象编程(2)
接口Go语言的主要设计者之一罗布·派克(Rob Pike)曾经说过,如果只能选择一个Go语言的特性移植到其他语言中,他会选择接口。接口在Go语言有着至关重要的地位。如果说goroutine和channel 是支撑起Go语言的并发模型的基石,让Go语言在如今集群化与多核化的时代成为一道极为亮丽的风景,那么接口是Go语言整个类型系统的基石,让Go语言在基础编程哲学的探索上达到前所未有的高度。Go语言在编程哲学上是变革派,而不是改良派。这不是因为Go语言有goroutine和channel,而更重要的是因为原创 2022-02-24 11:31:33 · 230 阅读 · 0 评论 -
996-Golang的面向对象编程(1)
类型系统很少有编程类的书谈及类型系统(type system)这个话题,实际上类型系统才是一门编程语言的地基,它的地位至关重要。因此,这里我们将从类型系统入手介绍Go语言的面向对象编程特性。顾名思义,类型系统是指一个语言的类型体系结构。一个典型的类型系统通常包含如下基本内容: 基础类型,如byte、int、bool、float等; 复合类型,如数组、结构体、指针等; 可以指向任意对象的类型(Any类型); 值语义和引用语义; 面向对象,即所有具备面向对象特征(比如成员方法)的类型;原创 2022-02-24 11:08:57 · 414 阅读 · 0 评论 -
995-Golang的RWMutex
前面我们聊了互斥锁Mutex,所谓读写锁RWMutex,完整的表述应该是读写互斥锁,可以说是Mutex的一个改进版, 在某些场景下可以发挥更加灵活的控制能力,比如:读取数据频率远远大于写数据频率的场景。例如,程序中写操作少而读操作多,简单的说,如果执行过程是1次写然后N次读的话,使用Mutex,这个过程将是串 行的,因为即便N次读操作互相之间并不影响,但也都需要持有Mutex后才可以操作。如果使用读写锁,多个读操作可 以同时持有锁,并发能力将大大提升。实现读写锁需要解决如下几个问题:写锁需要阻塞写锁原创 2022-02-22 21:10:07 · 1134 阅读 · 0 评论 -
994-Golang的mutex原理
互斥锁是并发程序中对共享资源进行访问控制的主要手段,对此Go语言提供了非常简单易用的Mutex,Mutex为一结构体类型,对外暴露两个方法Lock()和Unlock()分别用于加锁和解锁。Mutex使用起来非常方便,但其内部实现却复杂得多,这包括Mutex的几种状态。另外,我们也想探究一下Mutex重 复解锁引起panic的原因。Mutex数据结构Mutex结构体源码包 src/sync/mutex.go:Mutex 定义了互斥锁的数据结构:Mutex.state表示互斥锁的状态,比如是否被锁定原创 2022-02-22 17:48:45 · 564 阅读 · 0 评论 -
993-Golang的range原理
range是Golang提供的一种迭代遍历手段,可操作的类型有数组、切片、Map、channel等,实际使用频率非常高。探索range的实现机制是很有意思的事情,这可能会改变你使用range的习惯。题目一:切片遍历下面函数通过遍历切片,打印切片的下标和元素值,请问性能上有没有可优化的空间?程序解释:函数中使用for-range对切片进行遍历,获取切片的下标和元素素值,这里忽略函数的实际意义。参考答案:遍历过程中每次迭代会对index和value进行赋值,如果数据量大或者value类型为strin原创 2022-02-22 12:58:08 · 405 阅读 · 0 评论 -
992-Golang的select原理
select是Golang在语言层面提供的多路IO复用的机制,其可以检测多个channel是否ready(即是否可读或可写), 使用起来非常方便。本章试图根据源码总结其实现原理,从而发现一些使用误区或解释一些不太常见的现象。题目1下面的程序输出是什么?程序中声明两个channel,分别为chan1和chan2,依次启动两个协程,分别向两个channel中写入一个数据就进入 睡眠。select语句两个case分别检测chan1和chan2是否可读,如果都不可读则执行default语句。参考答案:原创 2022-02-22 10:35:41 · 757 阅读 · 0 评论 -
991-Golang的defer
defer语句用于延迟函数的调用,每次defer都会把一个函数压入栈中,函数返回前再把延迟的函数取出并执行。为了方便描述,我们把创建defer的函数称为主函数,defer语句后面的函数称为延迟函数。延迟函数可能有输入参数,这些参数可能来源于定义defer的函数,延迟函数也可能引用主函数用于返回的变量,也 就是说延迟函数可能会影响主函数的一些行为,这些场景下,如果不了解defer的规则很容易出错。其实官方说明的defer的三个原则很清楚,本节试图汇总defer的使用场景并做简单说明。题目一下面函数输原创 2022-02-22 09:20:14 · 194 阅读 · 0 评论 -
990-Golang的string
Go标准库 builtin 给出了所有内置类型的定义。源代码位于 src/builtin/builtin.go ,其中关于string的描述如 下:所以string是8比特字节的集合,通常但并不一定是UTF-8编码的文本。另外,还提到了两点,非常重要:string可以为空(长度为0),但不会是nil; string对象不可以修改。string 数据结构源码包 src/runtime/string.go:stringStruct 定义了string的数据结构:其数据结构很简单:stringS原创 2022-02-21 20:35:07 · 345 阅读 · 0 评论 -
989-Golang的struct
Go的struct声明允许字段附带 Tag 来对字段做一些标记。 该 Tag 不仅仅是一个字符串那么简单,因为其主要用于反射场景, reflect 包中提供了操作 Tag 的方法,所 以 Tag 写法也要遵循一定的规则。Tag的本质Tag规则Tag 本身是一个字符串,但字符串中却是: 以空格分隔的 key:value 对 。key : 必须是非空字符串,字符串不能包含控制字符、空格、引号、冒号。 value : 以双引号标记的字符串 注意:冒号前后不能有空格如下代码所示,如此写没有实际意义,仅用原创 2022-02-21 19:47:37 · 224 阅读 · 0 评论 -
988-Golang的map原理
Golang的map使用哈希表作为底层实现,一个哈希表里可以有多个哈希表节点,也即bucket,而每个bucket就保存 了map中的一个或一组键值对。map数据结构由 runtime/map.go/hmap 定义:下图展示一个拥有4个bucket的map:本例中, hmap.B=2 , 而hmap.buckets长度是2^B为4. 元素经过哈希运算后会落到某个bucket中进行存储。查 找过程类似。bucket 很多时候被翻译为桶,所谓的 哈希桶 实际上就是bucket。bucket数据结构原创 2022-02-21 18:18:49 · 530 阅读 · 0 评论 -
987-Golang的slice
Slice又称动态数组,依托数组实现,可以方便的进行扩容、传递等,实际使用中比数组更灵活。 正因为灵活,如果不了解其内部实现机制,有可能遭遇莫名的异常现象。Slice的实现原理很简单,本节试图根据真实的使用场景,在源码中总结实现原理。题目一下面程序输出什么?程序解释:main函数中定义了一个10个长度的整型数组array,然后定义了一个切片slice,切取数组的第6个元 素,最后打印slice的长度和容量,判断切片的第一个元素和数组的第6个元素地址是否相等。参考答案:slice跟据数组array原创 2022-02-21 09:41:14 · 201 阅读 · 0 评论 -
986-Golang的chan数据结构
chan数据结构channel是Golang在语言层面提供的goroutine间的通信方式,比Unix管道更易用也更轻便。channel主要用于进 程内各goroutine间通信,如果需要跨进程通信,建议使用分布式系统的方法来解决。本章从源码角度分析channel的实现机制,实际上这部分源码非常简单易读。chan数据结构从数据结构可以看出channel由队列、类型信息、goroutine等待队列组成,下面分别说明其原理。环形队列chan内部实现了一个环形队列作为其缓冲区,队列的长度是创建cha原创 2022-02-20 19:28:36 · 983 阅读 · 0 评论 -
985-Golang的协程详解
Goroutine调度是一个很复杂的机制,尽管Go源码中提供了大量的注释,但对其原理没有一个好的理解的情况下去读 源码收获不会很大。下面尝试用简单的语言描述一下Goroutine调度机制,在此基础上再去研读源码效果可能更好一 些。线程池的缺陷我们知道,在高并发应用中频繁创建线程会造成不必要的开销,所以有了线程池。线程池中预先保存一定数量的线 程,而新任务将不再以创建线程的方式去执行,而是将任务发布到任务队列,线程池中的线程不断的从任务队列中取 出任务并执行,可以有效的减少线程创建和销毁所带来的开销。下原创 2022-02-20 11:06:54 · 859 阅读 · 0 评论 -
984-Golang的反射
官方对此有个非常简明的介绍,两句话耐人寻味:反射提供一种让程序检查自身结构的能力反射是困惑的源泉第1条,再精确点的描述是“反射是一种检查interface变量的底层类型和值的机制”。第2条,很有喜感的自嘲,不过 往后看就笑不出来了,因为你很可能产生困惑. 想深入了解反射,必须深入理解类型和接口概念。下面开始复习一下这些基础概念。关于静态类型你肯定知道Go是静态类型语言,比如”int”、”float32”、”[]byte”等等。每个变量都有一个静态类型,且在编译 时就确定了。那么考虑一下如下原创 2022-02-20 10:57:16 · 211 阅读 · 0 评论 -
983-Golang的并发控制
我们考虑这么一种场景,协程A执行过程中需要创建子协程A1、A2、A3…An,协程A创建完子协程后就等待子协程退 出。针对这种场景,GO提供了三种解决方案:Channel: 使用channel控制子协程WaitGroup : 使用信号量机制控制子协程Context: 使用上下文控制子协程三种方案各有优劣,比如Channel优点是实现简单,清晰易懂,WaitGroup优点是子协程个数动态可调整,Context 优点是对子协程派生出来的孙子协程的控制。缺点是相对而言的,要结合实例应用场景进行选择。cha原创 2022-02-19 17:20:33 · 2184 阅读 · 0 评论 -
982-golang的逃逸分析
前言所谓逃逸分析(Escape analysis)是指由编译器决定内存分配的位置,不需要程序员指定。函数中申请一个新的 对象如果分配在栈中,则函数执行结束可自动将内存回收;如果分配在堆中,则函数执行结束可交给GC(垃圾回收)处理;有了逃逸分析,返回函数局部变量将变得可能,除此之外,逃逸分析还跟闭包息息相关,了解哪些场景下对象会逃逸 至关重要。逃逸策略每当函数中申请新的对象,编译器会跟据该对象是否被函数外部引用来决定是否逃逸:如果函数外部没有引用,则优先放到栈中;如果函数外部存在引用,则必定原创 2022-02-19 10:13:54 · 324 阅读 · 0 评论 -
981-golang的垃圾回收原理
前言所谓垃圾就是不再需要的内存块,这些垃圾如果不清理就没办法再次被分配使用,在不支持垃圾回收的编程语言里, 这些垃圾内存就是泄露的内存。Golang的垃圾回收(GC)也是内存管理的一部分,了解垃圾回收最好先了解前面介绍的内存分配原理。垃圾回收算法业界常见的垃圾回收算法有以下几种:引用计数:对每个对象维护一个引用计数,当引用该对象的对象被销毁时,引用计数减1,当引用计数器为0是 回收该对象。优点:对象可以很快的被回收,不会出现内存耗尽或达到某个阀值时才回收。缺点:不能很好的处理循环引用,而且实原创 2022-02-19 10:05:56 · 447 阅读 · 0 评论 -
980-golang的内存分配原理
前言编写过C语言程序的肯定知道通过malloc()方法动态申请内存,其中内存分配器使用的是glibc提供的ptmalloc2。 除了glibc,业界比较出名的内存分配器有Google的tcmalloc和Facebook的jemalloc。二者在避免内存碎片和 性能上均比glic有比较大的优势,在多线程环境中效果更明显。Golang中也实现了内存分配器,原理与tcmalloc类似,简单的说就是维护一块大的全局内存,每个线程(Golang中 为P)维护一块小的私有内存,私有内存不足再从全局申请。另外,内存原创 2022-02-19 09:58:06 · 895 阅读 · 0 评论 -
970-golang实现多线程服务端和客户端通信
package main import ( "net" "fmt" "time") func server(){ listen_sock, err := net.Listen("tcp", "0.0.0.0:8888") if err != nil { fmt.Println("listen error") return; } defer listen_sock.Close() conn, err := listen_sock.Accept() if err !=原创 2022-02-15 09:03:05 · 397 阅读 · 0 评论 -
616-Golang的包
包包:组织代码(开源的工具)包的里面还可以有别的包自己写1个包1、创建1个新的文件:go.mod(只能叫这个名字)Go语言通过识别1个目录下看有没有go.mod来识别这个是不是一个包如果没有,就认为只是些普通的文件,没有包2、在go.mod中声明包的名字还要声明这个包对应的go的版本是什么到现在为止,这个go的目录就变成1个包的空间了包声明 方法1.手动写 方法2.通过go生成方法1就是上面所叙述的我们接下来来看看方法2打开命令行然后我们打开go.mod原创 2021-09-21 09:01:26 · 104 阅读 · 0 评论 -
615-Golang的channel管道
channel管道channel-管道例程之间传递数据比如说有A,B两个例程,A放数据到channel,B从channel中读取数据1.自带阻塞(不用手动去检测)——读取一个没有数据的管道,就阻塞2.管道分类型3.管道初始化——要在main中进行channel的初始化管道的声明:int类型的管道空管道是不能使用的我们可以这样:打印出来的是管道的资源标识符两个例程之间数据的通信我们让主例程睡眠一下,让两个子例程都执行完我们完善代码ch<-12//往管道塞东西原创 2021-09-21 09:01:15 · 129 阅读 · 0 评论 -
614-Golang的go语句、死锁、线程间同步
并发处理使用go语句作用是帮我们启动一个新的例程出来go 函数()这个函数一旦开始执行,这个例程就启动了,一旦函数结束,这个例程就结束了下面这种情况是同步的,只有一个主例程。test先执行完,才执行打印bbb我们现在使用go 函数()test函数启动了一个新的例程,和主例程分开去并行了。现在是并发执行了(没有严格的谁块谁慢)打印的结可能是aaa bbb也有可能是bbb aaaaaa哪里去了?在Go语言的程序中,只要主例程结束了,这个程序就自动结束了,不会去管子例程有没有结束我原创 2021-09-21 09:01:03 · 242 阅读 · 0 评论 -
613-Golang的例程
Go不支持多线程,叫例程,例程是Go自身提供的,线程是系统提供的但是我们依然管它叫多线程CPU是计算机的本体现代计算机是多核的CPU,意味着如果同时一次只做1件事,计算机只能体现它八分之一(8个核)的性能,如何把CPU的性能发挥到极致?多线程,多进程,例程我们要充分发挥计算能力——同时完成多个工作例程和线程是一样的,大家共享一套资源。...原创 2021-09-21 09:00:51 · 160 阅读 · 0 评论 -
612-Golang的二进制文件
二进制文件二进制文件——最小的体积、最快的速度1、任何文件都相当于是一个大数组2、二进制文件都有格式规定我们先规定一下内容的格式4byte 后面有n个数字4byte 554byte 284byte 9....上面这个写法是错误的,转不了。我们该怎么办?多字节数据int64 相当于8*byte字节按照什么顺序排列?big endian 大端 符合人类的习惯little endian 小端 计算机适应的习惯为什么计算机适应的是小端?计算机在使用自己的内存原创 2021-09-21 09:00:30 · 1014 阅读 · 0 评论 -
611-Golang的关闭文件
ioutil是简化版的文件操作,它把容易出问题的操作在里面做完了,最后把结果给你返回过去,就是结束了,等于它在里面把文件的打开,读取, 关闭的这一系列操作都是它自己完成的,我们不用去担心考虑但是,如果我们用的是完整版的文件进行打开读取,即os.OpenFile,我们就得自己去管理文件了如果文件一直处于打开的状态,会出现很多很多的问题句柄(handle)——对资源的访问标识符,是个数字访问文件还是网络,还是系统的资源,都是会把句柄给你,相当于去饭店吃饭,要取个号,根据这个号排队吃饭。如果程序一旦原创 2021-09-21 09:00:18 · 792 阅读 · 0 评论 -
610-Golang的读写文件
读写文件的全部数据包:"io"聚集了大量的和输入输出相关的操作,和文件有关系WriteFile(“文件的路径”, 内容, 选项)我们看下面这个例子因为我们现在要写入文件,没有人规定这个文件只能装文本,它找我们要的是byte数组执行成功为什么我的权限是可以写的?我明明设置成只读的啊?权限在window上是不起作用的,在linux上起作用的现在咱们能写入文件了,接下来我们进行读文件ioutil.WriteFile(路径, 内容, 权限)ioutil.ReadFile(原创 2021-09-21 09:00:01 · 893 阅读 · 0 评论 -
609-Golang的Json
xml的格式:json的格式:JsonJson的输出json[{"name":"blue","age":18},{"name":"blue","age":18}]输出jsonimport "encoding/json"encoder:=json.NewEncoder(writer)encoder.Encode(数据)我们现在弄一个struct我们测试看看现在就可以了,因为首字母大写的公有的,可以输出出去的,Encode也是这个规则如果我们一定要输原创 2021-09-20 14:34:24 · 114 阅读 · 0 评论 -
608-Golang的make与new
创建对象makenew我们应该这么写:&的意思是,这个不是真正的对象,是一个指针我们继续看:我们现在给slice添加元素new适用于任何类型,而且想要几个就有几个总结应用如果不是一个用户呢?是一堆用户但是,实际上来说,存在一些问题这个程序的性能是很低的,当我们把创建的东西返回回去,被append接收到,是把整个对象复制到第一个还没被使用的格子上对象的复制,如果对象又特别的庞大,会导致程序的性能降低为了防止对象的复制,我们把它的地址拿过原创 2021-09-20 14:06:58 · 155 阅读 · 0 评论 -
607-Golang的map字典
map—字典key-value对可以快速的通过key找到对应的数据1.key必须唯一!!!2.key、value 都有对应的固定的类型map[key类型]value类型现在我们要向map里存放东西这个nil空不是说它里面没有数据,而是本身是个nil,所有我们需要这么做:make在slice中,和在map中的区别slicemake([]int, len, cap)mapmake(map[x]y, cap)map的容量没有办法通过cap来查看len是1,就是我们原创 2021-09-20 13:31:29 · 135 阅读 · 0 评论 -
606-Golang的slice切片
slice切片切片是数组的一部分,slice本身是数组的引用!!!也就是说,如果修改slice的"数据",array数组本身也会变切片声明var arr [5]int //arrayvar slice []int //slice 没有长度的数组被称为切片,只是数组的引用,我们举个例子:接下来,我们对数组进行切片比如说,我们想要数组中的5和8为什么是1:3?因为是不包含结束位置的!到slice里面是重新记录下标,但是在原数组中还是不变的接下来,我们对切片的值进行修改原创 2021-09-20 13:08:06 · 176 阅读 · 0 评论 -
605-Golang的for循环
循环-重复写法1:for 初始化; 条件; 自增 { 语句}写法2://类似于其他语言的while循环for 条件 { }写法1:进入for循环,首先进入到i:=0,这个是初始化的部分,这部分只会被执行1次,然后来到i<5这个判断条件,如果成立,处理{}里的语句(处理完之后,进入到自增i++,然后又回到条件判断i<5,以此类推),如果条件不成立,退出for循环。写法2:死循环:正确写法:可不可以使用下面这种形式的?答案是不可以的遍历-原创 2021-09-20 12:06:43 · 377 阅读 · 0 评论 -
604-Golang的数组
数组Golang的数组是定长的 和C语言类似1.下标——访问数组中的某个元素 arr[n]2.长度 len(arr) //长度 cap(arr) //容量简单定义一个长度是16的int类型的数组下标——访问数组中的某个元素如何获取数组的长度?len方法是返回数组的总长度cap方法也可以获取数组的容量对于Go的数组来说,len方法和cap方法相同,在别的地方是不同的数组的初始化数组初始化arr1:=[len]type{x,x,x,...}原创 2021-09-20 10:07:04 · 297 阅读 · 0 评论 -
603-Golang的if与switch
if判断写法1:写法2:这个代表:如果上面的if和else if的条件都不执行,就执行else里面的语句写法3:下面这种写法是正确的下面这种写法是错误的如果我们要给每个地区,定相应的数量这样写太费劲了!switch注意:Go中的switch是不需要break的,自带避免问题的能力...原创 2021-09-20 10:03:12 · 141 阅读 · 0 评论 -
602-Golang的操作符
操作符数学运算+ - * /% 求模-------------------------------------赋值=:=+= -= *= /= %=只有:a++ a-- 没有:++a --a&= |= ^=<<= >>=-------------------------------------比较==!=> < >= <=-------------------------------原创 2021-09-20 09:46:46 · 202 阅读 · 0 评论 -
601-Golang的method
struct结构体+方法现在我们觉得这个结构体太单薄了,它应该有自己的操作方法上述是通过一个函数来实现的让年龄加,但是现在这个函数和user是没有关联的,就是一个普通的结构外加一个普通的函数我们的Go提供了另外一种方案:struct结构体+方法func addAge(user *User, n int) { user.age+=n}//前面的这个参数表示:这个方法属于哪个struct的,只能传1个struct类型的参数func (user User) addAge(n in原创 2021-09-20 09:29:39 · 106 阅读 · 0 评论 -
600-Golang的函数应用
函数应用总结1函数——重用1.参数:输入2.返回值:输出指针——数据的地址a和num是两个变量,分别在两个栈帧空间上如果我们希望这个number被test函数修改为88,应该这么做我们要使用指针函数应用总结2函数应用总结3写法1:写法2:写法3:写法4:因为已经初始化了,可以让编译器判断是什么类型函数应用总结3这个时候把user传给test,是传值的形式,把user复制了一份丢给test的形参,如果user数据量空间大,复制拷贝的过程原创 2021-09-20 09:29:25 · 104 阅读 · 0 评论 -
599-Golang的函数基础
函数代码封装起来,为了重用func 名字() { 代码}func 名字(参数, 参数, ...) 返回值 {}函数:重用代码参数:函数的输入返回值:函数的输出我们先写一个简单的show函数我们写个有参数的函数:我们可以给函数添加返回值函数执行到return了,就结束了,后面的代码不会执行了,编译器会提示我们再举个例子我们的Go有很多库,其中math库有圆周率π文件操作go的函数可以有多个返回值func xxx(...) (int,原创 2021-09-19 20:45:18 · 200 阅读 · 0 评论 -
598-Golang的指针
指针指针(pointer)是存储一个地址地址:0x16F9 22D9&取址操作&xx => xx所在的内存地址内存的结构:计算机的内存很大,所以指针(地址)是以16进制表现出来的我们来打印一下变量的地址%d是纯数字,十进制的输出我们用%p,十六进制输出我们发现,每次输出的地址都是一样的我们可对任何东西取地址a和b在内存中是否是挨着的,每次输出是否会变化,都取决于系统分配b是指针类型a的指针不能赋值给intvar a int原创 2021-09-19 19:54:07 · 164 阅读 · 0 评论