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

golang常见面试题

1. go语言有哪些优点、特性?

语法简便,容易上手。

支持高并发,go有独特的协程概念,一般语言最小的执行单位是线程,go语言支持多开协程,协程是用户态线程,协程的占用内存更少,协程只独有自己的栈等一些资源。其他都是共享线程的。调度时可以极大减少上下文切换。

2. go的包管理

golang在1.11版本之前用的是GOPATH,项目代码要放在GOPATH/src目录下才可运行。但是GOPATH存在弊端,没有版本控制概念,go get的外部库,自己都不知道下载的什么版本,再多人协作开发时无法确定大家的外部库版本是否一致,会出大问题。

golang1.11后推荐使用go mod 管理,go env 下设置 GO111MODULE = on 打开。支持依赖升降级。


3. make和new 的一些区别

new 可以初始化声明所有类型,返回的是一个指针类型。对应的是该类型的空值

make 只能用来初始化 map slice channel 的,返回的就是这个类型。对应的是该类型的零值

new的用法不常见,一般使用 var 或 :=


4. channel 是可以被 close 的,之后还可以读写吗?

不管是有无缓冲channel。关闭后都可以读,读的是channel 传输类型的 零值。

不管是有无缓冲channel,关闭后都不可以写,写会panic


5. channel有什么用

channel 用来做协程之间的通信。go语言提倡不要用共享内存来通信,要用通信的方式来共享内存。channel就是利用通信的方式实现对资源的访问。

无缓冲channel可以用来做协程间的同步

有缓冲channel可以用来做消息队列

6. channel的底层结构?接收、发送消息的过程?

channel底层是一个结构体,里面包含一个环形缓冲区,还有接收等待队列和发送等待队列。分别存放等待写消息的协程队列和读消息的协程队列,还有一个互斥锁,用来保证channel的线程安全,防止多个协程并发读写。

当一个协程向channel写数据,如果是无缓冲通道,会将其加入到消息等待发送队列中,等待一个协程向channel读数据

读数据时,会先看缓冲区,如果没有再唤醒消息等待发送队列的第一个协程拿到信息,如果没有加入到消息等待接收队列,等待一个协程向channel写数据

7. channel 并发安全吗?

channel并发安全,底层结构体中有一个互斥锁,在并发环境下可以自动实现加锁解锁操作。


8. 怎么样输出一个有序的map

用slice存放map的key值,对slice进行排序,然后按照slice顺序查找map key value

用golang的数据结构 list来实现,list是一个链表。map[key]value value存放链表节点,写入map的时候同时按照顺序写入list中,顺序遍历时,只需要遍历链表即可。可以达到有序效果。


9. map在传参时的类型

golang传参都是值传递,只是对于map chan 等类型,他们在进行值拷贝的时候,调用的makechan 和 makemap 方法返回的都是指针类型的变量。导致操作的其实是同一个内存。

10. 可以直接对map取地址吗?

对map可以取址,但是对于map的key value不能取址,map不支持这种操作,当某种条件达到后,map会做增量扩容或者等量扩容操作。这时候每个key 的地址都可能发生变化。因此获取map key  value地址的操作是无意义的。

11. map底层结构

map底层是一个结构体,hmap,hmap中包含 元素的个数,桶的个数,以及指向桶数组的指针,每一个桶是一个bucket,bucket在go中用的是 bmap结构体,每个bucket可以存放 8个键值对,哈希值低八位相同的键存入bucket时会将高八位存储在tophash数组里。data 区域存放的key-value数据是按照 keykeykey valuevaluevalue存放的,overflow指针指向下一个bucket桶,通过链表将所有冲突的键连接起来。

12. 哪些数据类型不能作为map里面的key,哪些可以,有没有什么评判标准?

无法比较的数据类型都不能作为map里面的key。

基本数据类型都可作为key,指针也可以,因为指针比较的是地址。 数组也可以,结构体也可以

不可比较 map slice function

13. map是并发安全的吗?怎么实现并发安全?

map不是并发安全的,底层结构体没有用互斥锁进行加锁解锁操作。

如何实现并发安全,1.map+读写锁 (推荐)   2.用sync.Map


14. sync.Map如何解决并发问题?

sync.Map底层结构体中嵌入了一个互斥锁。。。。


15. gmp模型(局部饥饿、全局饥饿、全局缓存队列等)

最开始的时候,大多用线程池,开一定量的线程,当有工作任务到来时,会拿出一个线程处理,但当因为发生系统调用而阻塞时,线程池中可工作的线程就少了,线程池的性能就降低了。于是有了GMP模型。

G是协程,用户态线程

本地队列:每个P都有本地队列,本地队列中存放的是G

全局队列:当本地队列都满了,新来的G会优先加入本地队列中,本地队列满了会把本地队列的一半加入到全局队列

M是工作线程,用来处理协程的

P是处理器,默认数量是内核数,M通过获取P来处理P中的G

15. go有了协程之后,那它的线程是怎么调度的?(GMP模型)M最多多少个?

有调度策略:线程正常情况下会和P绑定,处理P中的本地队列G,但当处理G时,由于系统调用导致阻塞时,会触发hand off,M会和 P 解绑,把P转移给其他的空闲M,如果没有就创建一个新的M处理。如果M将P中的队列G处理完了,就会从其他P的本地队列中偷取一半协程来运行,如果其他都没有,就会从全局队列中选择一批来处理。

M最多10000个,在初始化运行时会设置最大值。但因为M需要获取到P才能处理G,P的数量是很有限的,所以M不会很多。

16. 线程数量和什么有关系?线程数量是无限大的吗?

线程数量和程序运行时,设置的最大M有关,默认是10000,并且跟P有关系,因为M必须要拿到P才能处理G。而且如果线程处理的阻塞的G完成后,可能会被销毁。不能无限大


16. slice深度拷贝

copy方法时,或者append触发扩容机制时都是深度拷贝。拷贝的是数据本身,新创建的对象和源对象不共享内存,会另开辟一个新的内存地址,值修改时不会影响源对象值。

17. slice和数组有什么区别?

slice 结构体中包含了 一个指向底层数组的指针还有slice的长度及容量

数组无法扩容,切片可以动态追加

数组声明时需要指定长度,切片不需要

数组是值类型的,切片是引用类型的


18. slice如何扩容?

1.18版本之前,当切片容量1024之前,每次扩容都是原来数组的二倍,当切片容量到1024之后,每次扩容都是原数组1.25倍

1.18版本,觉得扩容比例一下从2变成1.25有些不平滑,于是调整扩容机制,在容量小于256时,是2倍扩容,当容量大于256时,增加 (原来容量+3*256)/4。逐渐接近1.25倍,更平滑


19. interface{}怎么用

interface{}可以用来实现多态和符合设计模式的原则 依赖倒转 面向接口编程。 写一个接口,里面有要实现的方法,定义一个结构体,实现接口中的方法,然后初始化时,声明一个接口对象并指向具体的结构体,这样实现了面向接口编程,解耦。

也可以用来做强制类型转换,断言。interface.(type)


20. 说一下go的继承

go中的继承是通过结构体嵌套实现的,子结构体嵌套父结构体。初始化子结构体后,就可以用父结构体的方法。


21. go中哪些变量是不能比较的

map slice function 


22. golang强类型,弱类型?

golang是强类型语言,不会隐式的进行数据类型的转换。在速度上可能略逊弱类型语言,但是严谨性又避免了不必要的错误


23. golang并发控制?

可以用 Sync.WaitGroup实现  WaitGroup有三个方法,Add,Done,Wait。用来控制计数器数量。

可以用channel实现,goroutine之间通过channel通信,如果多个goroutine都写入channel,这时候通过缓冲区就可以实现并发控制,当缓冲区满时,后面的goroutine的写操作会被阻塞。


24. 一个go-routine最小占多大内存空间?

2kb


25. context类型有哪些?Context的作用是什么?context如何实现cancel的?

context主要用来在协程间传递关闭信号、信息的。可以控制多级协程

空context、cancelCtx、valueCtx、timerCtx。cancelCtx可以用来做协程的断开操作。




27. 正常模式和饥饿模式?

针对于互斥锁的,Mutex。正常模式下请求锁的协程要按照先入先出顺序排队,以此被唤醒,唤醒后还要与新请求锁的协程进行竞争,因为新请求的协程有优势,他们正在CPU上运行或者数量比较多。新唤醒的协程很难获取到锁,于是又会加到队列头部,如果一个等待的协程超过1ms仍未获取到锁,就会进入到饥饿模式。

饥饿模式下,互斥锁所有权会直接从解锁的协程转移到队首的协程,并且新到达的协程不会尝试获取锁而是加到队列尾部。如果一个等待协程获取到锁并且满足下面两个条件只一,就会回到正常模式。是队列的最后一个协程,等待时间小于1ms。

正常模式有更好的性能,饥饿模式可以避免尾部延迟这种情况


28. 用Go实现一个死锁

死锁存在四个条件,互斥,占有且等待,循环等待,不可强占用

func main() {ch1 := make(chan int)ch2 := make(chan int)var x sync.WaitGroupx.Add(2)go func() {ch2 <- 1fmt.Println(<-ch1)x.Done()}()go func() {fmt.Println(<-ch2)ch1 <- 1x.Done()}()x.Wait()
}


29. gc的了解

gc是垃圾回收机制,为了对堆栈上使用完的对象及时回收。防止内存溢出。最初1.3版本之前使用的是标记清除法,GC时会暂停程序进行标记清楚操作。STW时间很长。为了优化STW,1.3版本后缩短了一些STW时间,回收对象的操作放在STW时间之外。1.5版本时为了降低STW的时间,使用三色标记法+插入/删除屏障实现。三色标记法是在GC开始时,从根节点开始遍历所有可达对象,第一次遍历到的对象置灰,第二次遍历到的对象置黑。当没有灰色对象是开始回收对象。但是这样存在问题,当新创建了一个白色对象时,被一个黑色对象引用了,此时会造成刚创建的对象也被回收。还有当删除一个对象时,但是后面的对象还想要使用,但是断掉后后面的对象也会被回收。针对这两种情况提出了两个设计原则,强三色不变式和弱三色不变式,强三色强调黑色对象不能引用白色对象。弱三色不变式强调当黑色对象引用白色对象是,要保证还有一个灰色对象引用白色对象。针对这两个原则,产出了插入屏障和删除屏障,插入屏障实现的是强三色不变式,当黑色对象引用白色对象时,会将白色对象变为灰色对象。删除屏障实现的是弱三色不变式,当删除灰色后面的白色对象,会把删除的白色对象置灰。当扫描完没有灰色对象后,会将栈对象置白,启用STW,从新扫描一遍栈上的可达节点,最终删掉白色对象。插入屏障仍然需要re-scan栈上的节点。删除屏障,删除效率低,这次要删除的对象要等下次才能删掉。于是1.8版本后,采用三色标记法+混合写屏障。混合写屏障结合了插入和删除屏障的优点,栈上的对象不启用GC,扫描时会将所有栈上对象和新建对象置黑,针对堆上对象,所有创建和删除的对象都置灰。体现的是变形的弱三色不变式。1.8版本极大减少了STW时间,但并不是完全没有,因为在GC三色标记法之前还要STW,开启辅助GC和写屏障,统计根对象的任务数量等。


30. 什么时候会触发 golang GC 呢?

手动触发:调用runtime.GC来手动触发

定期触发:最长两分钟触发一次GC

内存达到一定值:每当内存扩大一倍时启用GC


31. 内存泄漏

创建的资源没有正常释放造成内存一直占用。也无法被GC回收。内存泄漏一般是程序员申请资源后没有手动去释放资源,关闭通道,解锁等。

通过pprof工具排查

32. go里面声明一个变量,它是放在栈上还是堆上?

内存逃逸,局部变量从栈上逃逸到堆上发生了内存逃逸。 

对于指针类型,因为分配内存时不知道是否存在外部引用,于是就将内存分配在堆中,防止函数结束后局部变量被回收。

如果数据量太大,栈放不下就会逃逸到堆中

interface类型上调用方法,编译时不知道是如何实现的,就会放到堆中。


33. 子goroutine的panic会不会被父g捕获

panic只能捕获本协程内部的错误,无法捕获子协程的错误

34. defer的先后顺序

defer满足栈的结构,先入后出。

35. defer什么情况下可以修改函数的返回值?

defer和return知识,return分为两步操作,第一步先将返回值赋给return,在准备返回之前要执行defer函数,执行完后才将结果返回。 如果定义了具名返回值,并且在defer时对这个变量进行了处理。那return 这个变量时就会修改。


36. golang 如何做超时控制?

1.timeAfter 这个函数会返回一个通道,并且过一段时间后会自动向通道发送一个数据。

2.context 的 withTimeout 和 withDeadline 方法,当到规定时间或超过某一时间后,会调用cancel方法来关闭channel。可以做超时控制


37. select 一般使用在什么场景

select一般与通道连用,用来监听多个通道的状态。

可以在多个通道中选择一个可用的操作来执行,如果没有一个通道准备就绪,select会执行defaule语句或者继续等待。

38.go程序运行顺序?

从main包开始执行,首先会导入引用的包,如果这个包里有init函数,会先执行这个包的init函数。

如果在main包定义了init函数,Go运行会在包导入后,全局变量初始化之前调用init函数。

调用之后会进行全局变量初始化操作,最终进入到main函数,是整个程序入口点。main函数执行后,程序会按照调用函数顺序依次执行其他函数。
 

相关文章:

golang常见面试题

1. go语言有哪些优点、特性&#xff1f; 语法简便&#xff0c;容易上手。 支持高并发&#xff0c;go有独特的协程概念&#xff0c;一般语言最小的执行单位是线程&#xff0c;go语言支持多开协程&#xff0c;协程是用户态线程&#xff0c;协程的占用内存更少&#xff0c;协程只…...

探索Python编程世界:从入门到精通

一.Python 从入门到精通 随着计算机科学的发展&#xff0c;编程已经成为了一种必备的技能。而 Python 作为一种简单易学、功能强大的编程语言&#xff0c;越来越受到人们的喜爱。本文将为初学者介绍 Python 编程的基础知识&#xff0c;帮助他们踏入 Python 编程的大门&#xf…...

Spark Shuffle Tracking 原理分析

Shuffle Tracking Shuffle Tracking 是 Spark 在没有 ESS(External Shuffle Service)情况&#xff0c;并且开启 Dynamic Allocation 的重要功能。如在 K8S 上运行 spark 没有 ESS。本文档所有的前提都是基于以上条件的。 如果开启了 ESS&#xff0c;那么 Executor 计算完后&a…...

Docker 干货系列 (持续更新)

dive 直接用本地镜像名称来启动&#xff0c;不需要走 hub dive.sh IMAGE_NAME"${1}" TMP_FILE/tmp/dive-tmp-image.tar docker save "$IMAGE_NAME" > $TMP_FILE && dive $TMP_FILE --sourcedocker-archive && rm $TMP_FILE示例&#…...

一.jwt token 前后端的逻辑

摘要 jwt token 前后端的交互逻辑&#xff0c;此部分只描述了一些交互逻辑&#xff0c;不涉及到真实应用的开发。 token的格式 tokenheader‘.’payload‘.’sign 第一次登陆的时候 判断http请求头中是否包含Authorization不包含则提示用户未登录当用户登录后&#xff0c;…...

day12_oop_抽象和接口

今日内容 零、 复习昨日 一、作业 二、抽象 三、接口 零、 复习昨日 final的作用 修饰类,类不能被继承修饰方法,方法不能重写[重点]修饰变量/属性,变成常量,不能更改 static修饰方法的特点 static修饰的方法,可以通过类名调用 static修饰的属性特点 在内存只有一份,被该类的所有…...

linux 将 api_key设置环境变量里

vi ~/.bashrc在最后添加api_key的环境变量 export GEMINI_API_KEYAIza**********WvpX7FwbdM刷新配置 source ~/.bashrc使用python 读取环境变量 import os gemini_api_key os.getenv(GEMINI_API_KEY) print(gemini_api_key)...

java八股文复习-----2024/03/03

1.接口和抽象类的区别 相似点&#xff1a; &#xff08;1&#xff09;接口和抽象类都不能被实例化 &#xff08;2&#xff09;实现接口或继承抽象类的普通子类都必须实现这些抽象方法 不同点&#xff1a; &#xff08;1&#xff09;抽象类可以包含普通方法和代码块&#x…...

UE4 Niagara 关卡3.4官方案例解析

Texture sampling is only supported on the GPU at the moment.(纹理采样目前仅在GPU上受支持) 效果&#xff1a;textures can be referenced within GPU particle systems。this demo maps a texture to a grid of particles&#xff08;纹理可以在GPU粒子系统中被引用这个演…...

C# Onnx segment-anything 分割万物 一键抠图

目录 介绍 效果 模型信息 sam_vit_b_decoder.onnx sam_vit_b_encoder.onnx 项目 代码 下载 C# Onnx segment-anything 分割万物 一键抠图 介绍 github地址&#xff1a;GitHub - facebookresearch/segment-anything: The repository provides code for running infere…...

Linux配置网卡功能

提示:工具下载链接在文章最后 目录 一.network功能介绍二.配置network功能2.1 network_ip配置检查 2.2 network_br配置2.2.1 配置的网桥原先不存在检查2.2.2 配置的网桥已存在-修改网桥IP检查2.2.3 配置的网桥已存在-只添加网卡到网桥里检查 2.3 network_bond配置检查 2.4 netw…...

【C++】十大排序算法之 归并排序 快速排序

本次介绍内容参考自&#xff1a;十大经典排序算法&#xff08;C实现&#xff09; - fengMisaka - 博客园 (cnblogs.com) 排序算法是《数据结构与算法》中最基本的算法之一。 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a;通过比较来决定元素间的相对次序…...

x-pack的破解方式和免费jar包!!可直接用!!

原理介绍 我们平时为es安装x-pack组件&#xff0c;用elasticsearch-plugin install x-pack &#xff0c;安装成功后。 1.cd $es目录/pulgins/x-pack 里面有一个x-pack-5.6.2.jar &#xff0c;将jar包反编译&#xff0c;然后将里面的licence的程序改下。再编译成jar包。 2…...

最新版本,Midjourney保姆级教程!

一、认识Midjourney 1.1、MidJourney是什么&#xff1f; 随着ChatGPT的横空出世&#xff0c;人类正式迈入AI元年&#xff0c;其中MidJourney便是AI绘图工具&#xff0c;它能根据用户输入的文字描述&#xff08;提示词&#xff09;生成绘画作品&#xff0c;不管是灵动的人物&a…...

Android中的几种定位方式调用详解

目前&#xff0c;移动端大致通过三种方式来进行设备定位&#xff1a;GPS、基站、wifi。本文就详细的讲解一下这几种定位方式和实现方法。 前言 android中我们一般使用LocationManager来获取位置信息&#xff0c;这里面有四中provider&#xff1a; public static final Strin…...

【软件测试】接口调不通排查分析+常遇面试题总结

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、接口调不通&am…...

c++基础学习第三天(指针,结构体)

c基础学习第三天&#xff08;指针&#xff0c;结构体&#xff09; 文章目录 1、指针1.1、指针的基本概念1.2、指针变量的定义和使用1.3、 指针所占内存空间1.4、空指针和野指针1.5、 const修饰指针1.5.1、const修饰指针-常量指针1.5.2、const修饰常量-指针常量1.5.3、const即修…...

【数仓】zookeeper软件安装及集群配置

相关文章 【数仓】基本概念、知识普及、核心技术【数仓】数据分层概念以及相关逻辑【数仓】Hadoop软件安装及使用&#xff08;集群配置&#xff09;【数仓】Hadoop集群配置常用参数说明 一、环境准备 准备3台虚拟机 Hadoop131&#xff1a;192.168.56.131Hadoop132&#xff…...

Qt 实现橡皮擦拭显示图片

1.简介 在一些游戏中看见类似解密破案的效果&#xff0c;使用手触摸去擦拭图片上的灰尘&#xff0c;然后显示最终的图片&#xff0c;所以也想试试Qt实现的效果。大家有自己想做的效果&#xff0c;都可以尝试。 以下是效果展示图。 可以控制橡皮擦的大小&#xff0c;进行擦拭…...

Vue3+Element-Plus中ELMessage样式丢失处理

Vu3Element-Plus项目中,element-plus使用按需引入有时会出现样式失效和在vscode中使用会报错[找不到名称“ElMessage”。ts(2304)]错误 ELMessage弹框样式丢失处理方法 使用按需引入就不能手动再引入 import { ElMessage } from "element-plus";ElMessage.success…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

GraphRAG优化新思路-开源的ROGRAG框架

目前的如微软开源的GraphRAG的工作流程都较为复杂&#xff0c;难以孤立地评估各个组件的贡献&#xff0c;传统的检索方法在处理复杂推理任务时可能不够有效&#xff0c;特别是在需要理解实体间关系或多跳知识的情况下。先说结论&#xff0c;看完后感觉这个框架性能上不会比Grap…...

用鸿蒙HarmonyOS5实现国际象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的国际象棋小游戏的完整实现代码&#xff0c;使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├── …...

基于小程序老人监护管理系统源码数据库文档

摘 要 近年来&#xff0c;随着我国人口老龄化问题日益严重&#xff0c;独居和居住养老机构的的老年人数量越来越多。而随着老年人数量的逐步增长&#xff0c;随之而来的是日益突出的老年人问题&#xff0c;尤其是老年人的健康问题&#xff0c;尤其是老年人产生健康问题后&…...