前语

「金三银四」这些Go面试题,看看你会几个?

昨日群友问我能不能收拾Go主流结构方面的面试题,安排!

这篇文章分享了gRPC、GoFrame、GoZero、GoMicro、GORM、Gin等主流结构的30道面试题和详解。

需求大厂面经的朋友们也能够在私信我

gRPC

1.gRPC是什么,有哪些优点?

gRPC是一种高功用、开源的远程过程调用(RPC)结构,它能够使不同渠道和言语之间的服务彼此通讯。它的优点包含:高效性、跨渠道、异步流处理、支撑多种言语、安全、易于运用和开源。

2.gRPC和REST的区别是什么?

REST是根据HTTP协议的一种风格,而gRPC是一个独立于协议的RPC结构。 REST根据资源的状况搬运,运用规范的HTTP办法,而gRPC运用协议缓冲区(Protocol Buffers)进行序列化和反序列化。 gRPC支撑异步流处理和双向流,而REST通常只支撑恳求/响应模式。

3.Protocol Buffers是什么,为什么它被用于gRPC中?

Protocol Buffers是一种言语中立、渠道中立、可扩展的序列化格局,它能够用于数据交换和耐久化。它被用于gRPC中,因为它能够完成高效的序列化和反序列化,然后提高了gRPC的功用和功率。

4.gRPC的流程是什么?

gRPC流程分为四个过程:界说服务、生成源代码、完成服务、发动服务。首要,需求界说要完成的服务及其接口,运用Protocol Buffers编写接口界说文件。其次,运用编译器生成客户端和服务器端的源代码。然后,完成生成的接口。最终,发动服务器并将其部署在恰当的方位。

5.gRPC支撑哪些类型的序列化?

gRPC支撑两种类型的序列化:二进制(运用Protocol Buffers)和JSON。其间,二进制序列化在功率和功用方面比JSON序列化更优异。可是,JSON序列化在可读性方面更好,能够便利地进行调试和测验。

GoFrame

1.什么是 GoFrame?与 Go 规范库有什么区别?

GoFrame 是一个强壮的 Go Web 运用开发结构,它供给了一系列优异的功用模块和常用工具,便利开发者快速构建高功用、高可用的 Web 运用程序。

相较于 Go 规范库,GoFrame 供给了更多的功用模块,例如:ORM、Cache、Session、WebSocket、邮件发送等等。此外,GoFrame 也供给了更友好的 API 和更好的功用。

2.goframe结构中,怎么运用中间件?

在goframe结构中运用中间件很简略。只需求在路由界说时运用中间件函数,例如:

s := g.Server()
s.Group("/", func(group *ghttp.RouterGroup) {
    group.Middleware(MiddlewareFunc)
    group.ALL("/user", UserHandler)
})

3.goframe结构中,怎么完成守时使命?

在goframe结构中完成守时使命很容易。能够运用gcron插件。该插件供给了简略的API用于创立和办理守时使命,例如:

// 创立守时使命
s := gcron.NewScheduler()
s.Every(1).Hour().Do(TaskFunc)
// 开始守时使命
s.Start()

4.goframe结构中,怎么完成文件上传和下载?

在goframe结构中完成文件上传和下载很容易。能够运用ghttp的相关办法进行操作,例如:

// 文件上传
uploadFile, err := r.UploadFile("file")
if err != nil {
    return err
}
uploadFile.Save("/path/to/save")
// 文件下载
r.Response().Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
r.Response().ServeFile(filepath)

5.GoFrame 中的 gvalid 组件是什么?怎么运用?

goframe结构供给了功用强壮、运用便捷、灵活易扩展的数据/表单校验组件,由gvalid组件完成。

gvalid组件完成了十分强壮的数据校验功用,内置了数十种常用的校验规矩,支撑单数据多规矩校验、多数据多规矩批量校验、自界说过错信息、自界说正则校验、自界说校验规矩注册、支撑i18n国际化处理、支撑struct tag规矩及提示信息绑定等等特性,是现在功用最强壮的Go数据校验模块。

Go-Zero

1.Go-Zero 是什么?它的主要功用是什么?它与其他 Go 结构有什么不同?

Go-Zero 是一个根据 Go 言语的微服务开发结构。它旨在供给简略、高效和可靠的微服务开发解决方案。Go-Zero 主要功用包含 RPC、缓存、限流、熔断、监控等。相较于其他 Go 结构,如 Gin 或 Beego,Go-Zero 愈加专心于微服务开发,并供给了更多的开箱即用的功用。

2.go-zero中怎么完成JWT认证授权?

go-zero中供给了go-jwt包来完成JWT认证授权。具体过程如下:

1)界说一个Claims结构体,包含需求存储到JWT token中的信息。

2)经过jwt.NewHS256([]byte(“your-secret”))创立一个JWT签名实例,将Claims结构体转换成token字符串。

3)经过jwt.ParseHS256(token, []byte(“your-secret”))验证token,并回来解析后的Claims结构体。

3.怎么运用go-zero完成异步使命?

go-zero中供给了go-queue包来完成异步使命。具体过程如下:

1)创立一个Redis连接池。

2)经过queue.New(queueConfig, redisConfig)创立一个行列实例。

3)经过producer := queue.NewProducer()创立一个生产者实例。

4)经过consumer := queue.NewConsumer(queueConfig, redisConfig)创立一个消费者实例。

5)经过producer.Enqueue(job)将使命放入行列。

6)经过consumer.Consume(processor)处理行列中的使命。

4. 怎么运用go-zero完成分布式缓存?

go-zero中供给了go-cache包来完成分布式缓存。具体过程如下:

1)创立一个Redis连接池。

2)经过cache.New(cacheConfig, redisConfig)创立一个缓存实例。

3)经过cache.Set(key, value, expireTime)将数据存入缓存中。

4)经过cache.Get(key)从缓存中获取数据。

5.怎么运用go-zero完成限流?

go-zero中供给了go-ratelimit包来完成限流。具体过程如下:

1)经过rate.NewLimiter(rate.Every(time.Second), 100)创立一个限流器实例,限制每秒处理100个恳求。

2)经过limiter.Allow()办法判别当前恳求是否被答应,若被答应则处理恳求,否则回来过错提示。

GIN

1.Gin结构有什么特色?

Gin是一个根据Go言语的Web结构,它供给了一些轻量级的工具,使得编写高功用的Web运用程序变得十分容易。Gin具有快速的路由器,中间件支撑和过错办理功用,同时还供给了自动化的API文档生成和参数绑定等功用。

2.Gin结构中的中间件是什么?

中间件是Gin结构的一个重要概念,它是一种在处理恳求之前或之后履行的函数。中间件通常用于处理恳求,如身份验证,日志记载和功用监测等。在Gin结构中,中间件能够依照需求在路由器级别或大局级别进行注册和运用。

3.怎么在Gin结构中处理跨域恳求?并给出代码

Gin结构供给了一个cors中间件,能够用来处理跨域恳求。在运用cors中间件时,能够指定答应跨域恳求的源地址,答应的恳求办法,答应的头信息等。例如:

r := gin.Default()
r.Use(cors.New(cors.Config{
  AllowOrigins: []string{"http://localhost:8080"},
  AllowMethods: []string{"PUT", "PATCH", "GET", "POST", "DELETE"},
  AllowHeaders: []string{"Origin"},
}))

4.怎么在Gin结构中完成文件上传?

在Gin结构中,能够运用MultipartForm函数来处理文件上传。MultipartForm函数会自动解析multipart/form-data格局的表单数据,并将文件保存在指定的目录中。例如:

func UploadFile(c *gin.Context) {
    file, err := c.FormFile("file")
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    filename := filepath.Base(file.Filename)
    if err := c.SaveUploadedFile(file, filename); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    c.JSON(http.StatusOK, gin.H{"filename": filename})
}

5.GoFrame 中的 gvalid 模块是什么?怎么运用?

goframe结构供给了功用强壮、运用便捷、灵活易扩展的数据/表单校验组件,由gvalid组件完成。

gvalid组件完成了十分强壮的数据校验功用,内置了数十种常用的校验规矩,支撑单数据多规矩校验、多数据多规矩批量校验、自界说过错信息、自界说正则校验、自界说校验规矩注册、支撑i18n国际化处理、支撑struct tag规矩及提示信息绑定等等特性,是现在功用最强壮的Go数据校验模块。

5.怎么在Gin结构中完成JWT认证?

在Gin结构中,能够运用jwt-go库来完成JWT认证。JWT认证流程通常包含登录,生成token,验证token等过程。在Gin结构中,能够运用中间件来完成JWT认证,例如:

func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        tokenString := c.GetHeader("Authorization")
        if tokenString == "" {
            c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "Authorization header required"})
            return
        }
        token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
            if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
                return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
            }          

GORM

1.GORM 怎么完成一对多和多对多联系的映射?

关于一对多联系,能够运用 GORM 的 BelongsTo 和 HasMany 办法完成映射。比方:

type User struct {
    ID        uint
    Name      string
    Addresses []Address
}
type Address struct {
    ID      uint
    UserID  uint
    Address string
}
// User 模型对应的表应该包含一个外键,指向 Address 表中的 UserID 字段
// 运用 BelongsTo 和 HasMany 办法进行相关
func (u *User) Addresses() []Address {
    var addresses []Address
    DB.Model(&u).Association("Addresses").Find(&addresses)
    return addresses
}
func (a *Address) User() User {
    var user User
    DB.Model(&a).Association("User").Find(&user)
    return user
}

关于多对多联系,能够运用 GORM 的 ManyToMany 办法完成映射。比方:

type User struct {
    ID       uint
    Name     string
    Articles []Article `gorm:"many2many:user_articles"`
}
type Article struct {
    ID      uint
    Title   string
    Content string
    Users   []User `gorm:"many2many:user_articles"`
}
// User 和 Article 之间的联系经过 user_articles 表进行映射

2.在运用 GORM 进行数据库查询时,怎么避免 N+1 查询的问题?

N+1 查询问题指的是在查询相关表时,如果运用了嵌套循环进行查询,就会发生大量的 SQL 查询。为了避免这个问题,能够运用 GORM 的 Preload 办法预先加载相关数据。比方:

// 查询 Users 以及它们的 Addresses
var users []User
DB.Preload("Addresses").Find(&users)

这个查询会一次性加载一切 User 和 Address 数据,避免了 N+1 查询问题。

3. 怎么运用 GORM 进行事务办理?

GORM 的事务办理运用 Begin、Commit 和 Rollback 办法完成。比方:

tx := DB.Begin()
defer func() {
    if r := recover(); r != nil {
        tx.Rollback()
    }
}()
// 在事务中履行一系列操作
if err := tx.Create(&user).Error; err != nil {
    tx.Rollback()
    return err
}
if err := tx.Create(&address).Error; err != nil {
    tx.Rollback()
    return err
}
// 提交事务
tx.Commit()

4.GORM 的 Preload 办法和 Joins 办法有什么区别?在什么状况下运用哪种办法更好?

Preload 办法是在查询时预加载相关数据,而 Joins 办法是经过 SQL JOIN 句子连接多个表查询数据。Preload 办法适用于相关表较少、数据量不大的状况;而 Joins 办法适用于相关表较多、数据量较大的状况。

5.怎么在 GORM 中运用原生 SQL 查询?

在 GORM 中,能够运用 Raw 办法来履行原生 SQL 查询。Raw 办法接受一个 SQL 查询字符串和可选的参数列表,并回来一个 *gorm.DB 目标,能够运用该目标进行进一步的查询操作。

下面是一个运用 Raw 办法履行原生 SQL 查询的示例:

import "gorm.io/gorm"
// ...
var users []User
result := db.Raw("SELECT * FROM users WHERE age > ?", 18).Scan(&users)
if result.Error != nil {
    // 处理过错
}

在上面的示例中,咱们运用 Raw 办法履行了一个简略的 SQL 查询,它将回来一切年龄大于 18 岁的用户。Scan 办法用于将查询结果映射到一个 []User 目标中。

还能够运用 Exec 办法来履行不需求回来值的 SQL 查询,如插入、更新或删去数据:

result := db.Exec("DELETE FROM users WHERE age < ?", 18)
if result.Error != nil {
    // 处理过错
}

在上面的示例中,咱们运用 Exec 办法履行一个删去句子,它将删去一切年龄小于 18 岁的用户。因为这个SQL不需求回来值,咱们只需检查 result.Error 是否为 nil 来判别查询是否成功。

请注意,运用原生 SQL 查询或许会使代码更难以维护和调试,因为它们不受 GORM 的自动迁移和其他便利功用的支撑。因此,应该尽或许地运用 GORM 供给的高档查询功用。

Go-Micro

1.什么是 go-micro?

go-micro 是一个微服务结构,它能够用于构建可伸缩和可维护的微服务运用程序。它支撑多种言语和传输协议,并供给了一系列服务发现、负载均衡、音讯传递和远程过程调用(RPC)等基础设施功用。

2.go-micro 支撑哪些传输协议?

go-micro 支撑多种传输协议,包含 HTTP、TCP 和 NATS。其间,HTTP 和 TCP 协议适用于内部服务之间的通讯,而 NATS 协议则适用于跨网络边界的通讯。

3.怎么运用 go-micro 进行服务发现和负载均衡?

go-micro 内置了服务发现和负载均衡功用,能够经过调用相关 API 完成。例如,能够运用 go-micro 的服务发现 API 来查找已注册的服务,并运用负载均衡 API 来将恳求分配到多个实例之间。

4.go-micro 支撑哪些音讯传递方法?

go-micro 支撑多种音讯传递方法,包含同步和异步音讯传递。同步音讯传递运用 RPC 机制,而异步音讯传递则运用音讯行列和事件驱动模式。

5.怎么运用 go-micro 进行测验?

go-micro 供给了一系列测验工具和测验结构,能够用于测验微服务运用程序的各个组件。其间,mock 测验工具能够用于模仿服务接口和行为,以及对服务进行单元测验。别的,go-micro 还供给了一些集成测验工具,例如 Docker 和 Kubernetes,能够用于测验多个服务之间的交互。

总结

有志者,事竟成,破釜沉舟,百二秦关终属楚。

苦心人,天不负,卧薪尝胆,三千越甲可吞吴。

就算就业环境再好,也有人找不到作业;即使就业环境不好,也肯定有人能找到作业。

中止诉苦和焦虑,要想找到好作业:项目+算法+陈腔滥调,都要硬,学起来吧!掘友们加油。

成功上岸

如果你不知道怎么写好简历,不知道在面试中怎么做好自我介绍和项目介绍:能够在私信我

也欢迎我们重视我的,点赞、留言、转发。你的支撑,是我更文的最大动力!

本文正在参加「金石方案」