当前位置: 首页 > news >正文

go 面试题

go 里的多态

面向对象中的 “多态” 指的同一个行为具有多种不同表现形式或形态的能力,具体是指一个类实例(对象)的相同方法在不同情形有不同表现形式。
多态也使得不同内部结构的对象可以共享相同的外部接口,也就是都是一套外部模板,内部实际是什么,只要符合规格就可以。在 Go 语言中,多态是通过接口来实现的:

type AnimalSounder interface {MakeDNA()
}func MakeSomeDNA(animalSounder AnimalSounder) {		// 参数是AnimalSounder接口类型animalSounder.MakeDNA()
}

java 和go 的区别

1. 基础对比

特性 Go Java
语言定位 系统编程 + 高并发服务 企业级应用 + 跨平台开发
类型系统 静态类型,简洁 静态类型,严格
编译方式 直接编译成机器码(无 JVM) 编译成字节码,运行在 JVM 上
运行效率 接近 C,启动快 有 JVM 开销,启动稍慢
语法复杂度 简洁,语法元素少 语法丰富,关键字和特性多

2. 面向对象

特性 Go Java
类 (class) 没有 class,用 struct 有 class
继承 不支持继承,强调组合 支持继承(单继承,多接口)
多态 接口(隐式实现) 接口(显式实现)+ 继承
封装 通过首字母大小写控制可见性 public / private / protected

3. 并发模型

特性 Go Java
并发模型 goroutine + channel(CSP 模型) 线程 + 线程池(共享内存+锁)
线程开销 goroutine 超轻量(KB 级) Java 线程较重(MB 级)
原生支持 内置 go 关键字和 channel 通过 ThreadExecutorService
并发编程难度 简单直观 需要锁、同步工具类

👉 Go 天生为高并发服务优化,而 Java 并发需要更多代码。


4. 内存 & GC

特性 Go Java
内存管理 自动 GC,无手动释放 自动 GC
GC 特性 追求低延迟(适合服务端) 高吞吐(可调 GC 策略)
指针 有指针,但安全(不能运算) 没有指针,完全引用

5. 开发生态

特性 Go Java
标准库 内置网络、并发支持强 丰富的 API,覆盖广
框架 偏轻量(gin, gRPC) 大量成熟框架(Spring, Hibernate)
社区 云原生 / 微服务强 企业级应用主流

6. 应用场景

  • Go:高并发服务器、微服务、云原生、容器(Docker、K8s)、区块链、DevOps 工具
  • Java:企业级系统、金融、电商、大型 Web 应用、Android

7. 总结一句话

  • Go:快、轻量、并发强 → 更适合 云原生、高并发服务
  • Java:成熟、完整、生态丰富 → 更适合 企业级应用、大型系统

go 里基本数据类型包括哪些

Go 的基本数据类型可以分为几大类:


1. 布尔类型

  • bool

    • 取值:truefalse
    • 默认值:false

2. 数值类型

整型

  • 有符号整数int8, int16, int32, int64, int

  • 无符号整数uint8, uint16, uint32, uint64, uint

  • 特殊整型

    • byteuint8 的别名
    • runeint32 的别名,表示 Unicode 码点
    • uintptr → 足够存放指针的无符号整数类型

浮点型

  • float32, float64

复数类型

  • complex64 (由两个 float32 组成)
  • complex128 (由两个 float64 组成)

3. 字符串类型

  • string

    • UTF-8 编码的字节序列组成
    • 不可变,一旦创建不能修改

4. 派生/复合类型(常用但不是最基础的)

  • 数组 ([n]T)
  • 切片 ([]T)
  • 字典(map) (map[K]V)
  • 结构体(struct)
  • 指针(*T)
  • 通道(chan T)
  • 接口(interface)
  • 函数类型(func)

go 语言遍历字符串的方式


1. 按 字节(byte) 遍历

s := "Hello, 世界"for i := 0; i < len(s); i++ {fmt.Printf("index: %d, byte: %x\n", i, s[i])
}
  • s[i] 取到的是 单个字节 (uint8)。
  • 如果字符串里有中文、Emoji 这种多字节字符,遍历出来的只是 UTF-8 编码的每个字节。

2. 按 字符(rune,Unicode 码点) 遍历

s := "Hello, 世界"for i, r := range s {fmt.Printf("index: %d, rune: %c\n", i, r)
}
  • range 会自动把字符串解码成 Unicode 码点 (rune,本质是 int32)。
  • i 是该字符在原始字符串里的 字节索引
  • r 是解码后的 Unicode 码点。
  • 推荐这种方式来正确处理中文、Emoji。

3. 转换成 []rune 后遍历

s := "Hello, 世界"
runes := []rune(s)for i, r := range runes {fmt.Printf("index: %d, rune: %c\n", i, r)
}
  • range 类似,但能按 字符索引(而不是字节索引)访问。
  • 更方便做字符串切割、反转等操作。

byte 和 rune 类型的区别


1. 类型定义

  • byteuint8 的别名,本质上是一个 无符号的 8 位整数,范围是 0~255
    常用于表示 原始数据 或者 单个 ASCII 字符

  • runeint32 的别名,本质上是一个 有符号的 32 位整数,范围是 -2^31 ~ 2^31-1
    通常用来表示 一个 Unicode 码点(Unicode Code Point)


2. 在字符串中的作用

Go 的字符串底层是 只读的 []byte

  • 如果用 byte 遍历字符串,拿到的是 UTF-8 编码后的字节序列,不一定能正确对应到“字符”。
  • 如果用 rune 遍历字符串,Go 会自动解码 UTF-8,拿到的是 完整的 Unicode 字符(码点)

3. 示例代码

package mainimport ("fmt"
)func main() {s := "你好Go"// 按 byte 遍历fmt.Println("按 byte 遍历:")for i := 0; i < len(s); i++ {fmt.Printf("%c ", s[i])}fmt.Println()// 按 rune 遍历fmt.Println("按 rune 遍历:")for _, r := range s {fmt.Printf("%c ", r)}
}

输出:

按 byte 遍历:
ä ½ ¥ å ¥½ G o 
按 rune 遍历:
你 好 G o 
  • byte 遍历时,UTF-8 编码的多字节字符(中文)被拆开,打印结果是乱码。
  • rune 遍历时,能正确得到

4. 总结对比表

特性 byte rune
本质 uint8 int32
表示范围 0–255 -2^31 ~ 2^31-1(足够放下所有 Unicode)
适用场景 原始字节操作,ASCII 字符 Unicode 字符,文本处理
遍历字符串 拆开 UTF-8 字节,可能乱码 正确解码 UTF-8,得到字符

GMP 代表什么 好,这个问题直接切到 Go 调度器的核心 👍

在 Go 的 GMP 调度模型里:


1. 三个核心概念

  • G(Goroutine)

    • 就是 Go 里的协程。
    • 每个 G 包含执行栈、状态、任务函数等信息。
    • G 只是运行的任务单元,本身不会执行。
  • M(Machine)

    • 操作系统的线程(内核线程)。
    • 真正执行代码的实体。
    • M 在执行时必须绑定一个 P,才能运行 goroutine。
  • P(Processor)

    • 调度器中的逻辑处理器,负责调度 G 到 M 上运行。
    • 每个 P 维护一个本地队列,存放等待执行的 G。
    • P 的数量决定了 Go 程序的最大并行度(默认等于 CPU 核数,可用 GOMAXPROCS 设置)。

GMP 调度流程

✅ 调度流程

  1. 创建 goroutine

    • 执行 go func() 时,Go 运行时会把一个新的 G 对象放入 当前 P 的本地队列
  2. 创建 Goroutine

    • 当通过 go func() 创建新的 Goroutine 时,G 会首先被加入到与当前 P 关联的本地队列中。
    • 如果 P 的本地队列已满(超过 256 个 G),则新的 G 会被放入全局队列。
  3. ** 调度与执行 **:

    • 每个 M 与一个 P 绑定,M 从 P 的本地队列中获取一个 G 来执行。
    • 如果 P 的本地队列为空,M 会尝试从全局队列或其他 P 的本地队列中偷取(work stealing)任务执行。
  4. 系统调用与阻塞:

    • 当 G 执行过程中发生阻塞或系统调用,M 也会被阻塞。这时,P 会解绑当前的 M,并尝试寻找或创建新的 M 来继续执行其他 G。阻塞结束后,原来的 M 会尝试重新绑定一个 P 继续执行。
http://www.hskmm.com/?act=detail&tid=18403

相关文章:

  • 论文笔记:How Can Recommender Systems Benefit from Large Language Models: A Survey - 详解
  • newDay04
  • 5.WPF控件---ComboBox - 实践
  • SQLserver 通过本地方式改SA密码
  • 2_2025.9.26_2
  • k8s部署Prometheus实战
  • day005
  • AI Compass前沿速览:Qwen3-Max、Mixboard、Qwen3-VL、Audio2Face、Vidu Q2 AI视频生成模型、Qwen3-LiveTranslate-全模态同传大模型
  • javaEE初阶————多线程进阶(1) - 教程
  • 软工9.26
  • 第五篇
  • 网络安全周报:AI监控工具与关键基础设施漏洞警报
  • 重链抗体(IgG2、IgG3)与传统抗体的核心区别:从结构到功能的全方位解析
  • 9.26总结
  • 重点行业数字化转型一图参透 - 智慧园区
  • RustDesk:免费开源的跨平台远程桌面解决方案
  • uniapp
  • Ext-js-即时入门-全-
  • Ext-js4-扩展开发指南-全-
  • ECMAScript6-学习指南-全-
  • JSP征婚信息实用的系统3kx16代码+源码+数据库+调试部署+开发环境
  • CSS属性
  • 基于大数据的水产品安全信息可视化分析框架【Hadoop、spark、可视化大屏、课程毕设、毕业选题、数据分析、资料爬取、数据可视化】
  • CSS值
  • 2025_Polar秋季赛_web全解
  • QT:如何初始化窗体尺寸大小
  • 题2
  • linux命令-rm
  • 2025.9.26
  • 基于Amazon S3设置AWS Transfer Family Web 应用程序 - 实践