type
status
date
slug
summary
tags
category
icon
password

go语言特性优点理解

1.go语言可以直接编译成机器码

go语言的编译器可以直接将go语言源码编译成机器码
但是像java就是先由源码编译成字节码,最后再由字节码编译成机器码
注意:go的编译最小单元是函数

2.go语言是一门静态类型语言

  • 静态类型语言
静态类型语言在变量声明时一定要指明变量的类型(变量的类型在声明时确定)
  • 动态类型语言
动态类型语言并不要求在变量声明时就指明变量的类型,而是在第一次给变量赋值时确定(在运行时根据变量值确定)

3.go语言的runtime调度机制

runtime包内的方法主要是与底层CPU有关,runtime包常用方法如下
  • const GOOS string =theGos
GOOS是指可执行程序的目标操作系统(将要在该操作系统上执行),如Windows等
  • func Gosched()
Gosched使当前go程放弃处理器,以让其他go程进行。他不会挂起当前go程,因此当前go程未来可能会恢复执行
  • func NumCPU()int
NumCPU返回本地机器的逻辑CPU个数
  • func GOROOT()
返回Go的根目录
  • func GOMAXPROCS()
该函数设置可同时执行的最大CPU数,并返回先前的设置
  • func Goexit()
Goexit函数会终止调用他的go程,在终止前会执行所有的defer函数

4.go语言的GC

  • GC回收垃圾时间
申请内存达到上一次进行垃圾回收后的两倍时(如上一次回收垃圾后内存占用为5M,则当内存占用为10M时进行垃圾回收),或者每过固定时间回收一次(两分钟)
  • GC的回收对象
GC回收当前空间中未被引用的空间(没有指针指向)
  • GC的回收机制——stw,三色标记与屏障机制
早期go语言的GC是STW机制,即停止当前程序然后回收垃圾,但是耗时长
现在的go语言的GC是STW,三色标记和屏障机制。首先GC仍然会stop the world,然后对程序中当前的变量进行标记,标记完后程序立马继续执行(通过屏障机制来保证垃圾回收正确)。三色标记过程如下:初始时所有变量都被标记为白色。若某个变量还未被遍历且有引用,将当前变量标记为灰色;若某个变量的后继已经被遍历且当前变量也被遍历,就将当前变量标记为黑色。最后进行垃圾回收时回收所有白色的变量即可
关于屏障机制(暂未了解)
注意:变量对象越多,GC的效率越低。在go语言中,链表、map属于多个对象,但是切片和数组属于一个对象

5.go语言函数中的变量逃逸

  • 函数返回值型
如:
一个问题:为什么 &newMusicManager不会被GC回收呢?
此时 &newMusicManager从函数中逃逸,编译器此时发现该变量从当前函数中逃逸,就不会在当前函数的栈上分配该变量,而是会在堆上分配该变量,并且时当前变量的引用加一,防止其被GC回收

6.go语言的跨平台特性

对于不能跨平台的语言(如java),需要虚拟机来实现跨平台
但是go语言的代码可以直接转换为二进制可执行文件。而且go语言拥有自己的链接器,不依赖于任何系统提供的编译器和链接器,这使得go语言编译出的二进制可执行文件几乎可以运行在任何系统环境中(就是针对不同的平台编译成对应的机器码)

7.go语言的Exception和Error

go语言将所有的Exception都当做Error抛出
  • 普通异常
被调用方返回error对象,调用方判断error对象(用户自己创建的error变量)
  • 严重异常
指的是中断性panic(比如除0、下表越界等),使用defer...recover...panic机制来捕获处理。严重异常一般由golang内部自动抛出,不需要用户主动抛出。

8.go语言的反射机制

反射是指在程序运行期对程序本身进行访问和修改的能力
go语言提供了一种机制在运行时更新和检查变量的值、调用变量的方法和变量支持的内在操作,但是在编译时并不知道这些变量的具体类型,这种机制被称为反射
支持反射的语言可以在程序编译期将变量的反射信息,如字段名称、类型信息、结构体信息等整合到可执行文件中,并给程序提供接口访问反射信息,这样就可以在程序运行期获取变量的反射信息,并且有能力修改他们

9.go语言的并发与协程

  • go语言goroutine机制
  • go语言协程间的信息传输
共享内存型传输:使用全局变量加上互斥锁来实现数据的共享
消息传递型传输:使用管道(channel)进行协程间的数据传输
go语言的channel保证同一个时间只有一个goroutine能够访问里面的数据

10.go语言的泛化类型

1)关于函数的形参和实参(认识泛型的必要性)

在go语言中,若函数声明时已经确定了传入参数和返回参数的类型,则该函数就无法用其他类型的变量调用
如:
该函数无法计算浮点数或者字符串的和。若要计算浮点数和字符串的和,就只能重新定义函数,这无疑会造成代码重复量大

2)go语言的泛型

看如下泛型的例子:
再看不使用泛型的例子:
可以发现,不同于一般的类型定义,泛型类型名称Slice后带了中括号,对各个部分做一个解说就是:
  • T就是上面介绍过的类型形参(Type parameter),在定义Slice类型的时候 T 代表的具体类型并不确定,类似一个占位符
  • int|float32|float64这部分被称为类型约束(Type constraint),中间的 | 的意思是告诉编译器,类型形参 T 只可以接收 int 或 float32 或 float64 这三种类型的实参
  • 中括号里的 T int|float32|float64这一整串因为定义了所有的类型形参(在这个例子里只有一个类型形参T),所以我们称其为 类型形参列表(type parameter list)
  • 这里新定义的类型名称叫 Slice[T]
此时类型变量中的T就类似于函数中的传参,在声明该变量时还要传入数据类型
如:
此时就声明了一个slice[int]类型的变量a,a是一个整型切片
注意:任何泛型类型都必须传入类型实参实例化才可以使用
如:
此时就要对T和S两个类型形参进行实例化
如:
此时T实例化为int,S实例化为[]int
注意:基础类型不能只有类型形参,如下:

11.go语言的关键字

  • defer
defer可以在程序的任意位置使用,遇到defer关键字时会将其后面的语句先入栈,然后在程序执行完毕后将该栈中的语句依次出栈执行
  • select
select语句只能用于channel信道的IO操作,每个case都必须是一个信道。
如果不设置 default条件,当没有IO操作发生时,select语句就会一直阻塞;
如果有一个或多个IO操作发生时,Go运行时会随机选择一个case执行,但此时将无法保证执行顺序;
对于case语句,如果存在信道值为nil的读写操作,则该分支将被忽略,可以理解为相当于从select语句中删除了这个case;
对于空的 select语句,会引起死锁;
对于在 for中的select语句,不能添加 default,否则会引起cpu占用过高的问题;

12.go语言面向对象编程

13.关于编程的一点基础知识

1)模拟

2)动态规划

3)深度优先搜索

4)广度优先搜索

14.go语言的等号比较

等号比较:

  1. 常见的有 bool、数值型、字符、指针、数组
  1. 像切片、map、函数等是不能比较的。
  1. 如果结构体的所有成员都可以比较,则可以比较(成员不包含切片等)
Go 中的数组是值类型,可比较,另外一方面,数组的长度也是数组类型的组成部分,所以 a 和 b 是不同的类型,是不能比较的,所以编译错误。
Slice,Map,函数是引用类型
输出结果为结构体可以比较
这道题目考的是结构体的比较,有几个需要注意的地方:
多重赋值
多重赋值分为两个步骤,有先后顺序:
所以赋值运算等同于 i, s[0] = 2, "Z"。

15.go语言死锁

2.sync.Mutex互斥锁就不举例子了,只要不发生重入一般不会死锁,它和读写锁之间不会相互影响
下面这种是没问题的,不会发生死锁
通道相关操作的死锁
缓存为0的通道,导致的死锁
同一个协程读写
缓存为0的通道,没有人读,你也写不了,没有人写,你也读不了,这正是一种死锁!
func main() {
ch := make(chan int, 0)
}
读取通道协程来迟了
我们可以看到,这条协程开辟在将数字写入到通道之后,因为没有人读,通道就不能再继续写了,然后写入通道的操作就一直阻塞。可能疑惑不是开辟了一条协程在读吗?但是那条协程开辟在写入通道之后,如果不能写入通道,这个时候连协程都创建不了了。
此时将go协程写在ch<-前就不会造成死锁
通道读写时,相互要求对方先读或者先写
package main
func main() {
teacher := make(chan string, 0)
student := make(chan string, 0)
}

16.go语言new和make函数的区别

Go语言中的 new 和 make 主要区别如下:
  • make 只能用来分配及初始化类型为 slice、map、chan 的数据。new 可以分配任意类型的数据;
  • new 分配返回的是指针,即类型 *Type。make 返回引用,即 Type;
  • new 分配的空间被清零。make 分配空间后,会进行初始化;
new函数返回的永远是类型的指针,指针指向分配类型的内存地址

17.go语言中defer和return

在此之前,先理解一下return返回值的运行机制:return并非原子操作,共分为赋值、返回值两步操作。
defer、return、返回值三者的执行是:return最先执行,先将结果写入返回值中(即赋值);接着defer开始执行一些收尾工作;最后函数携带当前返回值退出(即返回值)。
不带命名返回值
不会影响返回值,如果函数的返回值是无名的(不带命名返回值),则go语言会在执行return的时候会执行一个类似创建一个临时变量作为保存return值的动作。
有名返回值
有名返回值的函数,由于返回值在函数定义的时候已经将该变量进行定义,在执行return的时候会先执行返回值保存操作,而后续的defer函数会改变这个返回值(虽然defer是在return之后执行的,但是由于使用的函数定义的变量,所以执行defer操作后对该变量的修改会影响到return的值。

18.go语言的闭包

答:闭包是指在一个函数内部定义另一个函数,并且内部函数可以访问外部函数的局部变量。使用闭包可以实现一些高级特性,如函数式编程、延迟计算、事件驱动等。
Java数字电路设计与嵌入式系统开发
Loading...
Noah
Noah
永远年轻,永远热泪盈眶
公告
❗❗复习笔记问题❗❗
由于兼容性问题
导入md文件可能导致了一些格式错误
🌹如发现格式错误,请联系我~🌹
🌹如博客内容有误也欢迎指出~🌹