0%

go 每日一问

基础类

2022-06-13

问:与其他语言相比,使用 Go 有什么好处?

  • 与其他作为学术实验开始的语言不同,Go 代码的设计是务实的。每个功能 和语法决策都旨在让程序员的生活更轻松。
  • Golang 针对并发进行了优化,并且在规模上运行良好。
  • 由于单一的标准代码格式,Golang 通常被认为比其他语言更具可读性。
  • 自动垃圾收集明显比 Java 或 Python 更有效,因为它与程序同时执行。

2022-06-14

问:Golang 使用什么数据类型(都有哪些数据类型)?

  • 布尔型
  • 数字类型(整数、浮点数)
  • 字符串类型
  • 错误类型(error)
  • 派生类型
    • Pointer(指针类型)
    • Method(函数类型)
    • Interface(接口类型)
    • struct(结构体)
    • Array
    • Slice
    • Map
    • Channel

2022-06-15

问:Go 程序中的包是什么?
(pkg) 是 Go 工作区中包含 Go 源文件或其他包的目录。源文件中的每个函数、变量和类型都存储在链接包中。每个 Go 源文件都属于一个包,该包在文件顶部使用以下命令声明:
package <packagename>

2022-06-16

问:Go 支持什么形式的类型转换? 将整数转换为浮点数?
Go 支持 显式类型转换 以满足其严格的类型要求。

2022-06-17

问:Go 程序中的包是什么?
(pkg) 是 Go 工作区中包含 Go 源文件或其他包的目录。源文件中的每个函数、变量和类型都存储在链接包中。每个 Go 源文件都属于一个包,该包在文件顶部使用以下命令声明:
package <packagename>

2022-06-18

问:什么是 Goroutine? 如何停止它?

  • 将要并发执行的任务包装成一个函数,调用函数的时候加上 go 关键字,就能够开启一个 goroutine 去执行该函数的任务。

  • goroutine 对应的函数执行完,该 goroutine 就结束了。

  • 程序启动的时候会自动创建一个 goroutine 去执行 main 函数。

  • main 函数结束了,那么程序就结束了,由该程序启动的所有其他 goroutine 也都结束了。

  • goroutine 对应的函数执行结束了, goroutine 就结束了。

  • main 函数执行结束了,由 main 函数启动的 goroutine 也都结束了。

2022-06-19

问: 如何在运行时检查变量类型?
类型开关(Type Switch)是在运行时检查变量类型的最佳方式。类型开关按类型 而不是值来评估变量。每个 Switch 至少包含一个 case 用作条件语句,如果没 有一个 case 为真,则执行 default

2022-06-20

问: Go 两个接口之间可以存在什么关系?
如果两个接口有相同的方法列表,那么他们就是等价的,可以相互赋值。如果 接口 A 的方法列表是接口 B 的方法列表的子集,那么接口 B 可以赋值给接口 A。接口查询是否成功,要在运行期才能够确定。

2022-06-21

问: Go 当中同步锁有什么特点?作用是什么?
同步锁的特点:

  • Mutex:当一个 Goroutine(协程)获得了 Mutex 后,其他 Gorouline(协程)就只能进入等待之中,除非该 gorouline 释放了该 Mutex

  • RWMutex(读写锁):RWMutex 在读锁占用的情况下,会阻止写,但不阻止读;RWMutex 在写锁占用情况下,会阻止任何其他 goroutine(读和写)进来,整个锁相当于由该 goroutine(协程)独占。

    同步锁的作用:保证资源在使用时的独有性,不会因为并发而导致数据错乱,保证系统并发时的稳定性。

2022-06-22

问: Go 语言当中 Channel(通道)有什么特点,需要注意什么?

如果给一个 nilchannel 发送数据,会造成永远阻塞。
如果从一个 nil 的 channel 中接收数据,也会造成永久阻塞。 给一个已经关闭的 channel 发送数据, 会引起 panic
从一个已经关闭的 channel 接收数据, 如果缓冲区中为空,则返回一个 零 值。

2022-06-23

问:Go 语言中 cap 函数可以作用于哪些内容?
可以作用于的类型有:

  • array(数组)
  • slice(切片)
  • channel(通道)

2022-06-24

问:goconvey 是什么? 一般用来做什么? github: goconvey

  • goconvey 是一个支持 Golang 的单元测试框架
  • goconvey能够自动监控文件修改并启动测试,并可以将测试结果实时输出到 Web 界面
  • goconvey 提供了丰富的断言简化测试用例的编写

配置 elasticsearch

2022-06-25

问:Go 语言当中 new 的作用是什么?
new 创建一个该类型的实例,并且返回指向该实例的指针。new 函数是内建函数,函数定义:

1
func new(Type) *Type
  • 使用 new 函数来分配空间
  • 传递给 new 函数的是一个类型,而不是一个值
  • 返回值是指向这个新分配的地址的指针

2022-06-26

问:Go 语言中 make 的作用是什么?
make 的作用是为 slice, map, chan 的初始化 然后返回引用 make 函数是内 建函数,函数定义:

1
func make(Type, size IntegerType) Type

make(T, args) 函数的目的和 new(T) 不同 仅仅用于创建 slice, map, channel 而且返回类型是实例

2022-06-27

问:Printf()Sprintf()FprintF() 都是格式化输出,有什么不同?
虽然这三个函数,都是格式化输出,但是输出的目标不一样。

  • Printf 是标准输出,一般是屏幕,也可以重定向。
  • Sprintf() 是把格式化字符串输出到指定的字符串中。
  • Fprintf() 是把格式化字符串输出到文件中。

2022-06-28

问:Go 语言当中数组和切片的区别是什么?
数组: 数组固定长度。数组长度是数组类型的一部分,所以 [3]int[4]int 是两种不同的数组类型数组需要指定大小,不指定也会根据初始化,自动推算出大小, 大小不可改变。数组是通过值传递的。
切片: 切片可以改变长度。切片是轻量级的数据结构,三个属性,指针,长度,容量 不需要指定大小切片是地址传递(引用传递)可以通过数组来初始化,也可以 通过内置函数 make() 来初始化,初始化的时候 len=cap,然后进行扩容。

2022-06-29

问:Go 语言当中值传递和地址传递(引用传递)如何运用?有什么区别?举例说明

  • 值传递只会把参数的值复制一份放进对应的函数,两个变量的地址不同, 不可相互修改。
  • 地址传递(引用传递)会将变量本身传入对应的函数,在函数中可以对该变 量进行值内容的修改。

2022-06-30

问:Go 语言当中数组和切片在传递的时候的区别是什么?

  • 数组是值传递
  • 切片看上去像是引用传递,但其实是值传递。

2022-07-01

问:Go 语言是如何实现切片扩容的?
在数组容量小于 1024 时,扩容以当前容量2倍进行扩容。但到了 1024 之后, 每次是原容量四分之一左右。

2022-07-02

问:看下面代码的 defer 的执行顺序是什么? defer 的作用和特点是什么?

defer 的作用是:

你只需要在调用普通函数或方法前加上关键字 defer,就完成了 defer 所需要 的语法。当 defer 语句被执行时,跟在 defer 后面的函数会被延迟执行。直到 包含该 defer 语句的函数执行完毕时,defer 后的函数才会被执行,不论包含 defer 语句的函数是通过 return 正常结束,还是由于 panic 导致的异常结束。 你可以在一个函数中执行多条 defer 语句,它们的执行顺序与声明顺序相反。

defer 的常用场景:

  • defer 语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。
  • 通过 defer 机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。
  • 释放资源的 defer 应该直接跟在请求资源的语句后。

2022-07-03

问:Golang Slice 的底层实现?
切片是基于数组实现的,它的底层是数组,它自己本身非常小,可以理解为对底层数组的抽象。因为基于数组实现,所以它的底层的内存是连续分配的,效率非常高,还可以通过索引获得数据。切片本身并不是动态数组或者数组指针。它内部实现的数据结构通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内。切片本身是一个只读对象,其工作机制类似数组指针的一种封装。

切片对象非常小,是因为它是只有 3 个字段的数据结构:

  • 指向底层数组的指针
  • 切片的长度
  • 切片的容量

2022-07-04

问:Golang Slice 的扩容机制,有什么注意点?
Go 中切片扩容的策略是这样的:

  • 首先判断,如果新申请容量大于2倍的旧容量,最终容量就是新申请的容量
  • 否则判断,如果旧切片的长度小于1024,则最终容量就是旧容量的两倍
  • 否则判断,如果旧切片长度大于等于1024,则最终容量从旧容量开始循环增加原来的 1/4, 直到最终容量大于等于新申请的容量
  • 如果最终容量计算值溢出,则最终容量就是新申请容量

2022-07-05

问:扩容前后的 Slice 是否相同?

  • 原数组还有容量可以扩容(实际容量没有填充完),这种情况下,扩容以后的数组还是指向原来的数组,对一个切片的操作可能影响多个指针指向相同地址的 Slice
  • 原来数组的容量已经达到了最大值,再想扩容, Go 默认会先开一片内存区域,把原来的值拷贝过来,然后再执行 append() 操作。这种情况丝毫不影响原数组。
  • 要复制一个 Slice,最好使用 Copy 函数。
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道