没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
内容概要:本文档《Go 面试题持续整理中.docx》涵盖了一系列 Go 语言的核心概念和技术要点,通过问答形式详细解析了 Go 语言的基础语法、内存管理、并发机制、垃圾回收、数据结构、网络编程等方面的知识。文档不仅解释了基本概念,如指针、多返回值、协程(Goroutine)、rune 类型、map 操作、defer 机制等,还深入探讨了高级主题,如 CSP 并发模型、GMP 调度器、内存逃逸分析、垃圾回收算法、Epoll 原理、微服务架构设计等。此外,文档还介绍了 Go 语言的内存管理和优化技巧,如栈空间管理、互斥锁机制、数据竞争检测等。文档内容详尽,适合开发者深入理解和掌握 Go 语言的关键技术和最佳实践。 适合人群:具备一定编程基础,特别是对 Go 语言感兴趣的开发者,尤其是工作 1-5 年的研发人员。 使用场景及目标:①帮助开发者理解 Go 语言的核心概念和语法细节;②为面试准备提供全面的知识点覆盖;③指导开发者在实际项目中应用 Go 语言的最佳实践,如并发编程、内存管理、网络编程等。 其他说明:文档内容丰富且深入,不仅适合初学者入门学习,也适合有一定经验的开发者进一步巩固和提升技能。建议读者结合实际项目进行实践,以加深对 Go 语言的理解和应用。
资源推荐
资源详情
资源评论





























格式:pdf 资源大小:50.0MB 页数:325


: =
和 :=
import fmt
func main(){
a := 1
p := &a// 取 址 &
fmt.Printf("%d", *p);//取值*
}
// 交换函数
func swap(a, b *int) {
*a, *b = *b, *a
}
type A struct{}
func (a *A) fun(){}
_,err := errorDemo()
if err!=nil{
fmt.Println(err)
return
}
Go 面试题持续整理中
Q 的区别?
=是赋值变量,:=是定义变量
Q : 指针的作用
一个指针可以指向任意变量的地址,它所指向的地址在32位或64位机器上分别固定占4或8个字节。指针
的作用有:
获取变量的值
改变变量的值
用指针替代值传入函数,比如类的接收器就是这样的。
Q : Go 允许多个返回值吗?
可以。通常函数除了一般返回值还会返回一个error。
Q : Go 有异常类型吗?
有。Go用error类型代替try...catch语句,这样可以节省资源。同时增加代码可读性:

type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
// 多一个函数当作构造函数
func New(text string) error {
return &errorString{text}
}
type Builder struct {
addr *Builder // of receiver, to detect copies by value
buf []byte // 1
}
也可以用errors.New()来定义自己的异常。errors.Error()会返回异常的字符串表示。只要实现error接口
就可以定义自己的异常,
Q : 什么是协程(Goroutine)
协程是用户态轻量级线程,它是线程调度的基本单位。通常在函数前加上go关键字就能实现并发。一个
Goroutine会以一个很小的栈启动2KB或4KB,当遇到栈空间不足时,栈会自动伸缩, 因此可以轻易实
现
成千上万个goroutine同时启动。
Q : 如何高效地拼接字符串
拼接字符串的方式有:"+", fmt.Sprintf, strings.Builder, bytes.Buffer, strings.Join
1 "+"
使用+ 操作符进行拼接时,会对字符串进行遍历,计算并开辟一个新的空间来存储原来的两个字符串。
2
fmt.Sprintf
由于采用了接口参数,必须要用反射获取值,因此有性能损耗。
3
strings.Builder:
用WriteString()进行拼接,内部实现是指针+切片,同时String()返回拼接后的字符串,它是直接把[]byte
转换为string,从而避免变量拷贝。
strings.builder 的实现原理很简单,结构如下:
addr 字段主要是做copycheck , buf 字段是一个byte 类型的切片,这个就是用来存放字符串内容
的,提供的writeString() 方法就是像切片buf 中追加数据:

func (b *Builder) String() string {
return *(*string)(unsafe.Pointer(&b.buf))
}
}
lastRead readOp // last read operation, so that Unread* can work correctly.
// read at &buf[off], write at &buf[len(buf)]
int
[]byte // contents are the bytes buf[off : len(buf)]
buf
off
type Buffer struct {
func (b *Buffer) WriteString(s string) (n int, err error) {
b.lastRead = opInvalid
m, ok := b.tryGrowByReslice(len(s))
if !ok {
m = b.grow(len(s))
}
return copy(b.buf[m:], s), nil
}
func (b *Buffer) String() string {
if b == nil {
// Special case, useful in debugging.
return "<nil>"
}
return string(b.buf[b.off:])
}
提供的String 方法就是将[]byte 转换为string 类型,这里为了避免内存拷贝的问题,使用了强制转
换
来避免内存拷贝:
4
bytes.Buffer
bytes.Buffer 是一个一个缓冲byte 类型的缓冲器,这个缓冲器里存放着都是byte 。使用方式如下:
bytes.buffer 底层也是一个[]byte 切片,结构体如下:
因为bytes.Buffer 可以持续向Buffer 尾部写入数据,从Buffer 头部读取数据,所以off 字段用来记
录读取位置,再利用切片的cap 特性来知道写入位置,这个不是本次的重点,重点看一下WriteString
方法是如何拼接字符串的:
切片在创建时并不会申请内存块,只有在往里写数据时才会申请,首次申请的大小即为写入数据的大
小。如果写入的数据小于64字节,则按64字节申请。采用动态扩展 slice 的机制,字符串追加采用
copy 的方式将追加的部分拷贝到尾部, copy 是内置的拷贝函数,可以减少内存分配。
但是在将[]byte 转换为string 类型依旧使用了标准类型,所以会发生内存分配:
5
strings.join
func (b *Builder) WriteString(s string) (int, error) {
b.copyCheck()
b.buf = append(b.buf, s...)
return len(s), nil
}

strings.join 也是基于strings.builder 来实现的,并且可以自定义分隔符,代码如下:
唯一不同在于在join 方法内调用了b.Grow(n) 方法,这个是进行初步的容量分配,而前面计算的n的长
度就是我们要拼接的slice的长度,因为我们传入切片长度固定,所以提前进行容量分配可以减少内存分
配,很高效。
总结:
strings.Join ≈ strings.Builder > bytes.Buffer > "+" > fmt.Sprintf
参考资料:字符串拼接性能及原理
|
Go 语言高性能编程
|
极客兔兔
func Join(elems []string, sep string) string {
switch len(elems) {
case 0:
return ""
case 1:
return elems[0]
}
n := len(sep) * (len(elems) - 1)
for i := 0; i < len(elems); i++ {
n += len(elems[i])
}
var b Builder
b.Grow(n)
b.WriteString(elems[0])
for _, s := range elems[1:] {
b.WriteString(sep)
b.WriteString(s)
}
return b.String()
}
func main(){
a := []string{"a", "b", "c"}
//方式1:
ret := a[0] + a[1] + a[2]
//方式2:
ret := fmt.Sprintf(a[0],a[1],a[2])
//方式3:
var sb strings.Builder
sb.WriteString(a[0])
sb.WriteString(a[1])
sb.WriteString(a[2])
ret := sb.String()
//方式4:
buf := new(bytes.Buffer)
buf.Write(a[0])
buf.Write(a[1])
buf.Write(a[2])
ret := buf.String()
//方式5:
ret := strings.Join(a,"")
}

Q : 什么是 rune 类型
rune是int32的别名,用来区分字符值和整数值。比如utf-8汉字占3个字节,按照一般方法遍历汉字字符
串得到的是乱码,这个时候要将字符串转换为rune:
Q : 如何判断 map 中是否包含某个 key ?
Q : Go 支持默认参数或可选参数吗?
不支持。但是可以利用结构体参数,或者...传入参数切片。
Q : defer 的执行顺序
defer执行顺序和调用顺序相反,类似于栈先进后出。
Q : 如何交换 2 个变量的值?
对于变量而言a,b = b,a ; 对于指针而言*a,*b = *b, *a
Q : Go 语言 tag 的用处?
tag可以为结构体成员提供属性。常见的:
1.
json序列化或反序列化时字段的名称
2.
db: sqlx模块中对应的数据库字段名
3.
form: gin框架中对应的前端的数据字段名
4.
binding: 搭配 form 使用, 默认如果没查找到结构体中的某个字段则不报错值为空, binding为
required 代表没找到返回错误给前端
Q : 如何获取一个结构体的所有tag?
利用反射:
sample := " 我 爱 GO"
runeSamp := []rune(sample)
runeSamp[0] = '你'
fmt.Println(string(runeSamp))
var sample map[int]int
if _, ok := sample[10];ok{
}else{
}
剩余30页未读,继续阅读
资源评论


爱恨交织围巾

- 粉丝: 1072
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- PLC的物料分拣机械手自动化控制系统设计方案.doc
- 试析企业财务管理受到的会计信息化影响及对策.docx
- 计算机科学与技术医院实习报告.docx
- 自动编程实训参考空白研究分析报告.doc
- 关于插件技术在计算机软件技术中的应用价值.docx
- 基于Android平台的大学计算机基础课程APP设计与应用.docx
- 基于P2P模式下的大学生网络借贷的风险防范研究.docx
- 电梯模型PLC控制系统设计方案与调试.doc
- 基于大数据的学生成绩影响因素分析系统.docx
- 网络环境下情报学研究的知识化.docx
- Flet框架实现的毛主席七律《长征》的诗句楼梯斜梯排列效果自定义模板
- 智能仪表的CAN接口设计.doc
- “乐佳盟智能化社区”网站设计方案.doc
- kV变电站二次网络安全设备规范书.doc
- 物联网在图书馆管理中的关键技术分析.doc
- 高一计算机期末试题.doc
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



安全验证
文档复制为VIP权益,开通VIP直接复制
