Golang中级面试题

这篇具有很好参考价值的文章主要介绍了Golang中级面试题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  1. Goroutine 和线程的区别

Goroutine 是 Go 中并发执行函数或方法的方式。它比线程更轻量级,因为它的创建和销毁的代价更低。与线程相比,Goroutine
在运行时的栈空间要小得多,并且可以根据需要动态增长和缩小。同时,Go 运行时也负责在系统线程上调度所有 Goroutine 的执行,这使得
Goroutine 的使用更加方便且高效。

  1. Go 的垃圾回收

Go 使用的是标记清除(Mark and Sweep)的垃圾回收策略,这种策略分为“标记”和“清除”两个阶段。在“标记”阶段,GC
会遍历所有的活动对象(也就是还在使用的对象),然后标记它们。在“清除”阶段,GC 会遍历所有的对象,回收那些未被标记(即未被使用)的对象。从
Go 1.5 开始,Go 的 GC 还实现了并发执行的能力,也就是说,在 GC 执行的时候,应用的 Goroutine
依然可以继续运行,只在必要的时候停下来与 GC 进行同步

  1. Go 中如何使用接口

在 Go 中,接口是定义对象行为的方式,它是一种类型,定义了一组方法,但是没有实现。任何实现了这些方法的类型都被认为实现了该接口。例如:

type Shape interface {
    Area() float64
}

type Rectangle struct {
    Width, Height float64
}

// Rectangle implements the Shape interface
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

在这个例子中,Rectangle 实现了 Shape 接口,因为它定义了 Area 方法。

  1. 在 Go 中,何时应该使用指针而不是值

当你需要修改一个函数或方法的接收者,或者当你处理的对象很大并且你想要避免复制该对象时,你应该使用指针。另外,由于在 Go
中,所有的函数参数都是按值传递的,所以如果你想让一个函数修改其参数的值,你也需要使用指针。

  1. Go 中的切片(slice)和数组的区别

数组是具有固定长度的值序列,而切片则是对数组中的连续片段的引用。切片的长度可以在运行时改变,这使得它比数组更加灵活。数组和切片都是有序的元素集,但是它们在使用方式和用途上有所不同。例如,如果你知道你需要存储的元素数量,那么可以使用数组。如果你不知道你需要多少元素,或者你需要一个可以改变大小的容器,那么你应该使用切片。

  1. 零值

在 Go 语言中,当我们声明一个变量但不给它赋值时,该变量将会被自动初始化为该类型的零值。各类型的零值如下:
数值类型(int、float64 等)的零值为 0。 布尔类型的零值为 false。 字符串类型的零值为 “”(空字符串)。
指针类型的零值为 nil。 切片、函数、接口、映射(map)和通道(channel)类型的零值也都是 nil。

  1. 错误处理

Go 语言使用了一个特殊的类型,即 error 类型,来处理错误。你可以通过返回 error 类型的值来表示错误。如果一切正常,就返回
nil,否则返回一个包含错误信息的 error 类型的值。例如:

func divide(x, y float64) (float64, error) {
    if y == 0.0 {
        return 0.0, errors.New("Cannot divide by zero")
    }
    return x / y, nil
}
  1. Channel

Channel 是 Go 语言中用于协程间通信的数据结构,它是一种类型安全的队列。Channel
能够用来发送和接收值,并且这些操作是原子性的。在协程间同步或数据传递时会用到。例如:

func run(EX chan bool,TMax int){
    for {
        select {
        case <-EX:
            // 收到停止信号,停止运行任务
            tip("计划任务", "计划任务已退出", "./crontab/back.ico")
            return
        default:
            runTask()
            ONE1:
            for i:=0;i<(3600*TMax);i++{
                select{
                case <-EX:
                    EX<-true
                    break ONE1
                default:
                    time.Sleep(1*time.Second)
                }
                
            }
        }
    }

}
  1. Map

Map 是 Go
语言的一种内建数据类型,它是键值对的无序集合。键可以是任何可比较的类型,值可以是任何类型。例如,map[string]int
是一个键为字符串、值为整数的 map。map 是引用类型,可以使用 make 函数创建。

  1. defer 语句

在 Go 中,defer 语句用来延迟执行一个函数或方法,直到包含该 defer 语句的函数执行完毕。defer
常常用于处理成对的操作,如打开和关闭文件,连接和断开数据库,加锁和解锁等。

  1. 实现继承

Go 语言并没有提供传统的继承机制,而是通过组合和接口来实现代码的重用和多态性。我们可以在结构体中嵌入其他类型,以实现类似继承的效果。

type Animal struct {
    Name string
}

func (a *Animal) Move() {
    fmt.Printf("%s is moving\n", a.Name)
}

type Bird struct {
    Animal  // 嵌套Animal结构体,Bird拥有了Animal的所有字段和方法
    CanFly bool
}

func (b *Bird) Fly() {
    if b.CanFly {
        fmt.Printf("%s is flying\n", b.Name)
    } else {
        fmt.Printf("%s cannot fly\n", b.Name)
    }
}

func main() {
    b := Bird{}
    b.Name = "Sparrow"
    b.CanFly = true
    b.Move()
    b.Fly()
}
  1. 包(package)

在 Go 中,包是代码的集合,它提供了一种将代码组织为逻辑单元的方式。要在代码中使用其他包,可以通过 import
语句导入,然后通过包名来访问其公开的类型、函数等。

  1. range 关键字

range 关键字用于 for 循环中迭代数组、切片、字符串、map 或通道等。range 返回索引和元素值。例如:

nums := []int{1, 2, 3, 4, 5}
for i, num := range nums {
    fmt.Printf("index: %d, value: %d\n", i, num)
}

对于 map,range 返回键和值;对于通道,range 返回通道中的每个值。

  1. Go中如何使用反射:在Go中,反射由reflect包提供。反射可以在运行时检查类型和变量,例如它的值,是否可以被设置,它的地址等等。我们甚至可以修改这些值。举个简单的例子
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())
  1. Go的空接口:在Go中,空接口

interface{}不包含任何方法,因此所有类型都实现了空接口。它常被用于容纳任意类型的值。例如

func describe(i interface{}) {
    fmt.Printf("(%v, %T)\n", i, i)
}

func main() {
    describe(42)
    describe("hello")
}
  1. Go中的同步原语:Go提供了一些同步原语,如sync.Mutex和sync.RWMutex,用于在协程之间同步访问资源。以下是一个使用互斥锁的例子
var counter = 0
var lock sync.Mutex

func increment() {
    lock.Lock()
    defer lock.Unlock()
    counter++
    fmt.Println(counter)
}
  1. 只运行一次的代码段:在Go中,sync.Once的Do方法可以保证函数只被调用一次。这常被用于单例模式
var once sync.Once

func getInstance() *Singleton {
    once.Do(func() {
        instance = new(Singleton)
    })
    return instance
}
  1. 实现异步操作:Go中的goroutine(通过go关键字)和channel是实现异步操作的主要方式。例如
ch := make(chan int)

go func() {
    ch <- doSomething() // doSomething()将在新的goroutine中异步执行
}()

result := <-ch // 从ch接收结果
  1. 使用context控制并发:Go的context包可以让你发送取消信号给goroutine,或者设置超时。例如
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()

select {
case result := <-ch:
    fmt.Println("received result", result)
case <-ctx.Done():
    fmt.Println("timeout")
}
  1. Go的内存管理

Go有一个垃圾收集器,会自动释放不再使用的内存。当一个变量不再被引用时,垃圾收集器就会释放它的内存。Go也允许手动管理内存,例如通过使用指针。

  1. Go协程与其他语言的线程

Go的协程是轻量级的,可以在单个操作系统线程上运行多个协程。协程比线程更轻量级,创建和销毁的成本更低,而且可以更好地利用多核。

  1. 面向接口编程

在Go中,接口是定义和组织代码的主要工具。接口定义了一组方法,但是没有实现。任何实现了这些方法的类型都被认为实现了该接口。

  1. 处理panic和recover

Go中的panic函数会停止当前函数的执行,并开始在同一个goroutine中执行panic。recover函数可以捕获到panic,并返回传入panic的值。这样,我们可以在defer函数中使用recover,来捕获和处理panic。文章来源地址https://www.toymoban.com/news/detail-607517.html

goCopy codefunc main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from", r)
        }
    }()
    panic("a problem occurred")
}

到了这里,关于Golang中级面试题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记录一下postman汉化踩过的坑

    postman安装后会频繁的进行更新,每次更新后我们会发现,postman界面就会回到原来的英文界面。这是由于汉化包的版本和postman的版本不一致导致的。 postman汉化包的更新滞后于postman的更新,如果要成功将postman汉化,就要下载以前的版本保证postman的版本和汉化包的版本一致。

    2024年02月15日
    浏览(49)
  • Spark搭建日志,记录一些踩过的坑

    本人在Centos中使用三个虚拟机(node1,node2,node3)搭建hadoop与Spark分布式环境(具体见后记中的Hadoop安装),本文记录一些踩过的坑 解决办法:sudo chown -R 用户名 /spark(spark或者hadoop所在目录) 原理:文件的初始所有者不是用户名(如root),要把spark目录的初始所有者更换为自

    2024年03月14日
    浏览(86)
  • docker+selenium+firefox | 我踩过的坑

    为了实现SSPUBot不在我电脑上部署,我只能将其制成Docker。 要知道SSPUBot在开发的时候用了selenium+Firefox的想法开发,所以Docker里面必须要有Firefox,结果这就让见识到了最顽固的错误 selenium.common.exceptions.WebDriverException: Message: Process unexpectedly closed with status 255 我们还是省略我找的

    2024年01月22日
    浏览(56)
  • 关于python的mediapipe库踩过的坑

      大家好,我是csdn的博主: lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,vue领域博主 lqj_本人擅长微信小程序,前端,vue,等方面的知识 https://blog.csdn.net/lbcyllqj?spm=1000.2115.3001.5343 哔哩哔哩欢迎关注: 小淼前端 小淼前端的个人空间_哔哩哔哩_bilibil

    2024年01月17日
    浏览(39)
  • hql(hive sql)中的join及踩过的坑

    1 几种join方式 join join 对应于 inner join 内连接。 当多张表进行 join 的时候,所有表中与 on 条件中匹配的数据才会显示。 hql (即 hive sql )的 on 子句中只支持 and ,不支持 or ,也不支持 null 的对比。 left outer join 左外连接,也称为左连接。 以左表为基准,如果右表有条件匹配

    2024年01月21日
    浏览(44)
  • 嵌入式-stm32重要基础知识(及踩过的坑)

    1、固件库: 固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道, 向上提供用户函数调用的接口(API)。 2、CMSIS标准与固件库的关系 就是对固件库函数的要求。 ARM 公司为了能让不同的芯片公司生产的 Cortex-M3 芯片能在软件上基本兼容,和芯片生产商

    2024年02月04日
    浏览(61)
  • 微信小程序哪些wifi+tcp+udp踩过的坑

    1、wx.startWifi 开启wifi模块 2、如果需要展示wifi列表则调用 wx.getWifiList(Object object) 注意: 请求获取 Wi-Fi 列表。wifiList 数据会在 onGetWifiList 注册的回调中返回。 Android 调用前需要 用户授权 scope.userLocation。 iOS 上将跳转到系统设置中的微信设置页,需要用户手动进入「无线局域网

    2024年02月15日
    浏览(43)
  • vue前端预览pdf并加水印、ofd文件,控制打印、下载、另存,vue-pdf的使用方法以及在开发中所踩过的坑合集

    根据公司的实际项目需求,要求实现对pdf和ofd文件的预览,并且需要限制用户是否可以下载、打印、另存pdf、ofd文件,如果该用户可以打印、下载需要控制每个用户的下载次数以及可打印的次数。正常的预览pdf很简单,直接调用浏览器的预览就可以而且功能也比较全,但是一

    2024年02月16日
    浏览(185)
  • 真人踩过的坑,告诉你避免自动化测试常犯的10个错误

    虽然从自己的错误中学习也不错,但从别人的错误中学习总是更好的。 作为一个自动化测试人员,分享常见的容易犯的10个错误,可以从中吸取教训,引以为鉴。 一、必要时才自动化 新人小王接到为Web应用程序自动化测试脚本的任务时,既高兴又紧张,因为这是他进入团队

    2023年04月08日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包