切片与数组的对比

  1. 数组
    1. 数组是具有固定长度且拥有零个或者多个相同数据类型元素的序列
    2. 数组的长度是数组类型的一部分,所以[3]int[4]int是两种不同的数组类型
    3. 数组需要指定大小,不指定也会根据初始化自动推算出大小,不可改变
    4. 数组是值传递
    5. 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值。在初始化后长度是固定的,无法修改其长度。当作为方法的参数传入时将复制一份数组而不是引用同一指针,数组的长度也是其类型的一部分,通过内置函数len(array)获取其长度
  2. 切片

    1. 切片表示一个拥有相同类型元素的可变长度的序列
    2. 切片是一种轻量级的数据结构,他有三个属性:指针、长度和容量
    3. 切片是地址传递
    4. 切片可以通过数组来初始化,也可以通过内置函数make()初始化,初始化时len=cap,在追加元素时如果容量cap不足时将按len的2倍扩容
    5. 切片的结构如下
      1. type Slice struct {
      2. ptr unsafe.Pointer
      3. len int
      4. cap int
      5. }
  3. 关系

一个底层数组可以对应多个slice,这些slice可以引用数组的任何位置,彼此之间的元素还可以重叠。

在go语言中,new和make的区别

  1. New
    1. new的作用时初始化一个指向类型的指针(*T)
    2. new函数是内建函数,函数定义:func new(Type) *Type
    3. 使用new函数来分配空间。传递给new函数是一个类型,不是一个值。返回值是指向这个新分配的零值的指针。
  2. make
    1. make的作用是为slice,map或chan初始化并返回引用(T)
    2. make函数是内建函数,函数定义:func make(Type, size IntergerType) Type,第一个参数是一个类型,第二个参数是长度,返回值是一个类型
    3. make(T,args)函数的目的与new(T)不同,它仅仅用于创建slice,Map和Channel,并且返回类型是T(不是*T)的一个初始化的(不是零值)的实例

      Printf(),Sprintf(),Fprintf()函数的区别用法是什么

      都是把格式化好的字符串输出,只是输出的目标不一样:
  • Printf() 是把格式字符串输出到标准输出,是和标准输出文件(stdout)关联的,Fprintf则没有这个限制
  • Sprintf() 是把格式字符串输出到指定字符串中,所以参数比printf多一个char*,那就是目标字符串地址
  • Fprintf() 是把格式字符串输出到指定文件设备中,所以参数比printf多一个文件指针FILE*,主要用于文件操作。Fprintf()是格式化输出到一个stream,通常是文件

    Go语言中的引用类型包含哪些

    数组切片、字典(map)、通道(channel)、接口(interface),其他都是值类型

    解释以下命令的作用

  • go env 用于查看go的环境变量

  • go run 用于编译并运行go源码文件
  • go build 用于编译源码文件、代码包、依赖包
  • go get 用于动态获取远程代码包
  • go install 用于编译go文件,并将编译结构安装到binpkg目录
  • go clean 用于清理工作目录,删除编译和安装遗留的目标文件
  • go version 用于查看go的版本信息

    说说go语言中的协程

    是什么
    进程和线程是操作系统内核实现的系统资源分配调度的单元(进程是资源分配和调度的基本单元,线程是处理器调度和分配的基本单元),相比而言,协程是一种程序自己实现的调度方式,它不是被操作系统内核所管理的,而是完全由程序所控制的。Go语言中的协程是由go实现的,用于实现程序并发执行的基本单元。

为什么
使用多线程和多进程总是存在一个问题,因为线程和进程是由内核实现的,在创建多线程和多进程的过程中难免需要成本进行创建和管理(系统调用开销,上下文切换开销,状态保存开销,在多线程中还有同步竞争的问题),会伴随着高CPU调度消耗和高内存占用(进程占用4GB,线程占用4MB)。因此,考虑在内核空间中建立一些线程,然后在用户空间中开辟一些协程去与其绑定以减少系统资源的开销。

怎么做
在go语言中,在函数调用前添加go关键字即可实现go的协程,创建并发任务。在协程运行的过程中,可以通过channel来进行协程间的通信(本质就是共享一块内存)

go语言中指针运算有哪些

  1. & 取指针的地址
  2. * 取指针指向的数据

    go语言中的for循环

  3. for循环支持continuebreak来控制循环,但是它提供了一个更高级的break,可以选择中断哪一个循环

  4. for循环不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量

image.png

Go语言中共的switch语句

  1. 单个case中,可以出现多结果选项
  2. 只有在case中明确添加fallthrough关键字,才会继续执行紧跟的下一个case

    go语言中没有隐藏的this指针,这句话是什么意思

  3. 方法施加的对象显式传递,没有被隐藏起来

  4. golang的面向对象表达更加直观,对于面向过程只是换了一种语法形式来表达
  5. 方法施加的对象不需要非的是指针,也不用非的叫this

    map如何顺序读取

    map不能顺序读取,因为它是无序的,想要有序读取,首先解决的问题就是把key变为有序,所以可以把key放入切片,对切片进行排序,遍历切片,通过key取值

    slice,len,cap,共享,扩容

    append函数,因为slice底层数据结构是由数组、len、cap组成,所以,在使用append扩容时,会查看数组后面有没有连续内存块,有就在后面添加,没有就重新生成一个大的数组

    说说go语言的main函数

  6. main函数不能带参数

  7. main函数不能定义返回值
  8. main函数所在的包必须为main包
  9. main函数中可以使用flag包来获取和解析命令行参数

    说说go语言的同步锁

  10. 当一个goroutine获得了Mutex后,其他goroutine就只能乖乖的等待,除非该goroutine释放了Mutex

  11. RWMutex读锁占用的情况下,会阻止写,但不阻止读
  12. RWMutex在写锁占用的情况下,会阻止任何其他goroutine(无论读和写)进来,整个锁相当于由该goroutine独占。

Go语言竞争状态

说说go语言的channel特性

  1. 给一个nil channel发送数据,造成永久阻塞
  2. 给一个nil channel接收数据,造成永久阻塞
  3. 给一个已经关闭的channel发送数据,引起panic
  4. 从一个已经关闭的channel接收数据,如果缓冲区中为空,则返回一个零值
  5. 无缓冲的channel是同步的,而由缓冲的channel是非同步的。 ```go c1:=make(chan int) 无缓冲

c2:=make(chan int,1) 有缓冲

  1. <a name="IPCS8"></a>
  2. # go语言触发异常的场景有哪些
  3. 1. 空指针解析
  4. 1. 下标越界
  5. 1. 除数为0
  6. 1. 调用panic函数
  7. <a name="7Wvak"></a>
  8. # 说说go语言的beego框架
  9. 1. beego是一个golang实现的轻量级HTTP框架
  10. 1. beego可以通过注释路由、正则路由等多种方式完成url路由注入
  11. 1. 可以使用bee new工具生成空工程,然后使用bee run命令自动热编译
  12. > gin框架
  13. 1. gin 的orm
  14. `gorm`是go语言中实现数据库访问的ORM(对象关系映射)库。使用这个库,我们可以利用面向对象的方法,更加方便地对数据库中地数据进行CRUD
  15. <a name="NvyT1"></a>
  16. # 说说go语言地goconvey框架(测试)
  17. 1. goconvey是一个支持golang的单元测试框架
  18. 1. gocenvey能够自动监控文件修改并启动测试,并可以将测试结果实时输出到web界面
  19. 1. goconvey提供了丰富的断言简化测试用例的编写
  20. <a name="QjRBZ"></a>
  21. # go语言中,gostub的作用是什么(测试)
  22. 1. gostub可以对全局变量打桩
  23. 1. gostub可以对函数打桩
  24. 1. gostub不可以对类成员方法打桩
  25. 1. gostub可以打动态桩,比如对一个函数打桩后,多次调用该函数会有不同的行为
  26. <a name="V2jWX"></a>
  27. # 说说go语言的select机制
  28. 1. select机制用来处理异步IO问题
  29. 1. select机制最大的一条限制就是每个case语句里必须是以一个IO操作
  30. 1. golang在语言级别支持select关键字
  31. ```go
  32. //select基本用法
  33. select {
  34. case <- chan1:
  35. // 如果chan1成功读到数据,则进行该case处理语句
  36. case chan2 <- 1:
  37. // 如果成功向chan2写入数据,则进行该case处理语句
  38. default:
  39. // 如果上面都没有成功,则进入default处理流程

说一说进程、线程、协程的区别

进程、线程与协程

Go struct能不能比较

因为是强类型语言,所以不同类型的结构不能做比较,但同一类型的实例值是可以比较的,实例不可以比较,因为是指针类型。

select可以用于什么

常用于goroutine的完美退出,golang的select就是监听I/O操作,当IO发生时,触发相应的动作
每个case语句里必须是一个IO操作,确切的说,应该是一个面向channel的IO操作

context包的用途

context通常被译作上下文,它用于上下层的传递,可以用于goroutine间传递

主协程如何等待其余协程完成后再操作

使用channel进行通信、context、select,waitgroup

实现消息队列

使用切片加锁可以实现

select是随机的还是顺序的

select会随机选择一个可用通道做收发操作

介绍下平时怎么调试golang的bug以及性能问题的

panic调用栈,pprof,go run -race ,查看系统 磁盘IO/网络IO/内存占用/CPU占用

IO : pidstat -u 1
网络IO: netstat -antop |grep 1.1.1.1
内存: pidstat -r 1
上下文切换: pidstat -w -p 1234

top

select的随机性

image.png
select会随机选择一个可用通道做收发操作,所以代码是有可能触发异常,也可能不会。单个chan如果无缓冲时,将会阻塞,但结合select可以在多个chan间等待执行,有三点原则:

  • select中只要有一个case能return,则立刻执行
  • 当如果同一时间有多个case能return,则立刻执行
  • 如果没有一个case能return,则可以执行default块

    切片输出

    image.png