结构体⽐较规则之⼀: 只有相同的类型的结构体才可以⽐较(1 结构体的属性类型, 2 属性的顺序)
本文是 Go 基础常见面试题,结合ChatGPT的详细解释版,全背是不可能,假如面试碰上了,挑出要点用自己的语言回答就好了。 1. 与其他语言相比,Go 语言的优点有哪些? 强大的标准库:Go 有一个丰富的标准库,尤其是对于网络编程和 Web 服务。 工具链:Go 语言自带一套完整的工具,如 go fmt 用于格式化代码,go get用于管理依赖等。 Goroutine 是 Go 语言的并发执行单元,它是一个轻量级的线程,由 Go 运行时管理。 Go 的参数传递、引用类型 在 Go 语言中,所有的参数传递都是按值传递。 了解这些细节有助于编写更有效率和更可预测的 Go 程序。 25. Go map 底层实现 在 Go 语言中,map是一种内置的数据结构,它是一个无序的键值对集合。
Mutex 几种状态 在 Go 语言的同步库中,sync.Mutex是用来提供互斥锁的基本同步原语。 互斥锁在内部状态实现可能因 Go 语言的不同版本而有所不同。 Go 的 Mutex 设计尝试确保公平性,避免长时间等待的 goroutine 处于饥饿状态。 Go 语言团队不断优化sync.Mutex,以找到公平和效率之间的平衡点。有关 sync.Mutex 的更多权威信息,建议查看最新的 Go 语言源码和文档。 3. 需要注意的是,在实现细节方面,Go 的标准库不提供关于互斥锁内部行为的具体参数。自旋的逻辑和上述条件可能在 Go 不同的版本之间有所变化,以上内容主要基于 Go 语言当前和之前版本的实现。
在go语言中,new和make的区别? go语言中协程 协程和线程都可以实现程序的并发执行; 通过channel来进行协程间的通信; 只需要在函数调用前添加go关键字即可实现go的协程,创建并发任务; 关键字go并非执行并发任务 在Go语言中,程序单元也就指的是Goroutine go语言的select机制 for { select { case <-chan1: //..... Go语言局部变量分配在栈还是堆? Go语言编译器会自动决定把一个变量放在栈还是放在堆,编译器会做逃逸分析,当发现变量的作用域没有跑出函数范围,就可以在栈上,反之则必须分配在堆。 如何获取 go 程序运行时的协程数量, gc 时间, 对象数, 堆栈信息?
Go 语言笔试面试题 日常收集的题 一. 基础语法 1 = 和 := 的区别? 答案 := 声明+赋值 = 仅赋值 1var a int 2a = 10 3// 等价于 4a := 10 2 Go 有异常类型吗? 答案 Go 没有异常类型,只有错误类型(Error),通常使用返回值来表示异常状态。 1f, err := os.Open("/tmp/a.txt") 2if err ! 6 var y int = M 7 fmt.Println(x, y) 8} 答案 编译失败:cannot use M (type int32) as type int in assignment Go
选择Go语言的原因: 并发和高并发:Go 语言在设计之初就考虑了并发和高并发方面的问题,将其内置于语言层面上,在编写代码时容易实现并发,提升程序的性能。 高效率:Go 语言的速度非常快(如 C/C++),同时又简单易用(如 Python)。Go 语言通过 Go 语言自身的编译器即可生成本地机器码,无需虚拟机,加快了执行效率。 开发工具丰富:Go语言是开源的,所以有很多优秀的开发工具,例如Goland、Visual Studio Code等。 学习曲线低:Go 语言语法类似于C/C++,容易学习,对于其他编程语言的用户来说更加容易上手。 例如,在高并发的Web应用程序中,Go 语言被广泛应用,如微服务框架、云原生应用开发、区块链等。 Go语言的优秀性能和高可靠性已经在实际应用中得到了验证。
Goroutine 的定义 在 Go 语言中,goroutine 是一种非常轻量级的执行线程。goroutine 是 Go 语言并发模型的核心,允许同时执行多个函数调用。 并发简单:Go 语言提供的 goroutines 使并发编程变得更简洁易懂。通过go关键字,开发者可以非常方便地启动新的并发任务。 需要注意的使,Go 的调度器细节可能随着版本更新而变化,上述描述适用于 1.x 系列的 Go 版本。 5. Go 1.14 版本引入了基于信号的抢占,这标志着 Go 语言实现了抢占式调度的一大步。 8. 升级 Go 版本:Go 团队不断优化 GC 机制。新的 Go 版本可能会带来更优化的 GC 行为,因此保持在最新的稳定版可以使应用受益于这些优化。 在调优之前,了解应用的内存使用模式是很重要的。
引用类型的内存在堆中分配,当没有任何变量引用堆中的内存地址时,该内存地址对应的数据存储空间就变成了垃圾,就会被GO语言的GC回收。 五、堆和栈 堆:在Go中,栈的内存是由编译器自动进行分配和释放,栈区往往存储着函数参数、局部变量和调用函数帧,它们随着函数的创建而分配,函数的退出而销毁。 注意:在go中 var是声明关键字,不会开辟内存空间;使用 := 或者 make 关键字进行初始化时才会开辟内存空间。 七、深拷贝和浅拷贝 操作对象 深拷贝和浅拷贝操作的对象都是Go语言中的引用类型 区别如下: 引用类型的特点是在内存中存储的是其他值的内存地址;而值类型在内存中存储的是真实的值。 九、go的map实现排序 我们知道go语言的map类型底层是有hash实现的,是无序的,不支持排序。 如果我们的数据使用map类型存储,如何实现排序呢?
Go语言、C++和Java语言是三种性能较好的编程语言,它们在某些方面有不同的优势。下面是一个简单的比较: 内存管理 C++需要手动管理内存,而Java和Go语言使用垃圾回收机制。 Go语言的垃圾回收机制与Java相似,但是Go语言在设计上更加注重高性能和高并发,在实际生产环境中表现也很好。 Java和Go语言在执行速度方面与C++相差不大,但是Go语言在处理高并发方面更加出色,因为Goroutines使Go代码并发执行非常容易。 而Go语言使用Goroutines和Channels来处理并发性,使得Go语言非常适合于高并发场景,简单易用。 如果你需要处理高并发,则选择Go语言。
答案 init() 函数是 Go 程序初始化的一部分。 Go 程序初始化先于 main 函数,由 runtime 初始化每个导入的包,初始化顺序不是按照从上到下的导入顺序,而是按照解析的依赖关系,没有依赖的包最先初始化。 答案 Go 语言中,interface 的内部实现包含了 2 个字段,类型 T 和 值 V,interface 可以使用 == 或 != 比较。 Q5 简述 Go 语言GC(垃圾回收)的工作原理 答案 最常见的垃圾回收算法有标记清除(Mark-Sweep) 和引用计数(Reference Count),Go 语言采用的是标记清除算法。 答案 这在 Go 中是安全的,Go 编译器将会对每个局部变量进行逃逸分析。如果发现局部变量的作用域超出该函数,则不会将内存分配在栈上,而是分配在堆上。
Go应用程序同时运行数千个 Goroutine 是非常常见的做法。 Q6 如何高效地拼接字符串 答案 Go 语言中,字符串是只读的,也就意味着每次修改操作都会创建一个新的字符串。 []rune("Go语言") 意思是字符串类型转换为 rune 切片类型。 //每个中文utf8 编码 占3个byte fmt.Println(len("Go语言")) // 8 fmt.Println(len([]rune("Go语言"))) // 4 Q8 如何判断 map Q9 Go 支持默认参数或可选参数吗? 答案:Go 语言不支持可选参数(python 支持),也不支持方法重载(java支持)。 但是返回值并没有被修改,这是由于 Go 的返回机制决定的,执行 return 语句后,Go 会创建一个临时变量保存返回值,因此,defer 语句修改了局部变量 i,并没有修改返回值。
例如: func main() { st := time.Now() ch := make(chan bool) go func () { time.Sleep time.Sleep(time.Second * 5) } func main() { st := time.Now() ch := make(chan bool, 2) go func query() int { ch := make(chan int) for i := 0; i < 1000; i++ { go func() { ch <- There is no limit to the number of threads that can be blocked in system calls on behalf of Go code; 1 从官方文档的解释可以看到,GOMAXPROCS 限制的是同时执行用户态 Go 代码的操作系统线程的数量,但是对于被系统调用阻塞的线程数量是没有限制的。
文章目录 启动两个协程,交替打印 123456 写一个程序,控制 Goruntine 数量 记录 Go 语言常见的编程面试题。 创建 3 个通道,A、B 和 Exit A := make(chan bool) B := make(chan bool) Exit := make(chan bool) go = <-A; ok { fmt.Println("A 输出", i) B <- true } } }() go ; i < taskCount; i++ { wg.Add(1) // 如果通道满了,就会阻塞 ch <- true // 开启一个新协程 go bizMethod(ch, i) } wg.Wait() } // 业务方法 func bizMethod(ch chan bool, i int) { fmt.Println("go
以下是使用go语言实现两数之和的代码,已加上详细注释: package main import "fmt" // twoSum 函数接收一个整形数组 nums 和一个目标值 target,返回满足条件的两个数的索引
以下是使用 go 语言实现最长公共前缀的代码,已加上详细注释: package main import "fmt" // longestCommonPrefix 函数接收一个字符串数组,返回这些字符串的最长公共前缀
u.Add(fmt.Sprintf("user_%d", i), i) gw.Done() } for i := 0; i < count; i++ { go add(i) go add(i) } for i := 0; i < count; i++ { go func(i int) {
令牌桶算法是一种常见的限流算法,它基于一个简单的思想:系统中的请求像一个桶。在请求发送之前都需要从桶中获取一个令牌,如果桶里没有可用的令牌,则该请求会被暂时禁止。
print("There are", count, "prime numbers between 1 and 200") # print the total count of prime numbers go # 测试 str1 = "abcdefg" str2 = "defghijk" print(find_longest_common_substring(str1, str2)) # 输出 "def" go 语言 // 使用go语言,求两个字符串的最长公共子串,并给出中文注释 func longestCommonSubstring(s1, s2 string) string { // 构建一个二维数组
解答题:go相关 go的调度 答: go的调度原理是基于GMP模型,G代表一个goroutine,不限制数量;M=machine,代表一个线程,最大1万,所有G任务还是在M上执行;P=processor go调用过程: 创建一个G对象 如果还有空闲的的P,创建一个M M会启动一个底层线程,循环执行能找到的G G的执行顺序是先从本地队列找,本地没找到从全局队列找。 一次性转移(全局G个数/P个数)个,再去其它P中找(一次性转移一半) 以上的G任务是按照队列顺序执行(也就是go函数的调用顺序)。 go struct能不能比较 答: 可以能,也可以不能。 因为go存在不能使用==判断类型:map、slice,如果struct包含这些类型的字段,则不能比较。 这两种类型也不能作为map的key。 go defer(for defer) 答: 类似栈操作,后进先出。
HTTP使用文本基础的协议,而gRPC使用的是二进制协议,这意味着gRPC数据包更小,传输效率更高。另外,gRPC使用HTTP/2协议,支持多路复用,从而可以更好地处理并发请求。