Go语言开发小技巧易错点100例(十二)

往期回顾:

  • Go语言开发小技巧&易错点100例(一)
  • Go语言开发小技巧&易错点100例(二)
  • Go语言开发小技巧&易错点100例(三)
  • Go语言开发小技巧&易错点100例(四)
  • Go语言开发小技巧&易错点100例(五)
  • Go语言开发小技巧&易错点100例(六)
  • Go语言开发小技巧&易错点100例(七)
  • Go语言开发小技巧&易错点100例(八)
  • Go语言开发小技巧&易错点100例(九)
  • Go语言开发小技巧&易错点100例(十)
  • Go语言开发小技巧&易错点100例(十一)

本期看点(技巧类用【技】表示,易错点用【易】表示)

  • Go HTTP全局异常处理器【技】
  • Go反射【技】

正文开始:

Go HTTP全局异常处理器

在Go语言中,使用net/http包构建HTTP服务器时,全局异常处理器通常指的是一个中间件,它可以捕获所有未被其他处理程序捕获的异常,并对它们进行统一的错误处理。这包括HTTP响应错误(如404 Not Found或500 Internal Server Error)以及可能的panic错误。

下面是一个如何实现全局异常处理器的例子:

package mainimport ("fmt""log""net/http"
)// 全局异常处理器
func globalErrorHandler(err error, w http.ResponseWriter, r *http.Request) {// 记录错误信息log.Printf("Error: %v", err)// 设置HTTP状态码if httpErr, ok := err.(*http.Error); ok {w.WriteHeader(httpErr.Code)} else {w.WriteHeader(http.StatusInternalServerError)}// 返回错误消息给客户端w.Write([]byte(err.Error()))
}// 自定义HTTP错误处理函数
func handleError(w http.ResponseWriter, r *http.Request, err error) {// 在这里你可以根据需要对错误进行特殊处理// 如果没有特殊处理,则调用全局异常处理器globalErrorHandler(err, w, r)
}// 示例HTTP处理函数
func helloHandler(w http.ResponseWriter, r *http.Request) {// 示例:故意制造一个错误panic("Something went wrong!")
}func main() {// 设置自定义错误处理函数http.DefaultServeMux.HandleFunc("/", helloHandler)http.DefaultServeMux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("OK"))})// 使用自定义错误处理函数作为全局异常处理器http.DefaultServeMux.HandlerFunc("/global-error-handler").Func = func(w http.ResponseWriter, r *http.Request) {defer func() {if err := recover(); err != nil {handleError(w, r, err)}}()http.NotFound(w, r)}fmt.Println("Server is running at http://localhost:8080")log.Fatal(http.ListenAndServe(":8080", nil))
}

在上面的例子中,globalErrorHandler 函数被设计为一个通用的错误处理器,它可以处理由handleError函数传递过来的错误。而handleError函数则作为一个桥接器,它既可以被直接调用,也可以在需要捕获panic的地方被defer语句调用。

helloHandler函数故意制造了一个panic错误,这个错误会被defer捕获,并传递给handleError函数,最后由globalErrorHandler统一处理。

需要注意的是,在真实的应用中,全局异常处理器可能需要处理更多种类的错误,包括自定义错误、第三方库错误等。此外,对于大型应用,通常会使用更复杂的错误处理机制,如错误包装(error wrapping)和日志记录(logging)等。

此外,如果你使用的是像Gin这样的Web框架,它们通常有自己的中间件机制来处理全局异常,这样可以使错误处理更加灵活和强大。

Go反射

在Go语言的编程世界中,反射(Reflection)是一个强大的工具,它允许程序在运行时检查、修改和调用对象的类型和值。虽然反射提供了极大的灵活性,但也需要谨慎使用,因为它可能会破坏封装性并降低性能。在本文中,我们将深入了解Go语言的反射机制,探讨其用法、优点和潜在陷阱。

一、什么是反射?

反射是一种在运行时检查、修改和调用对象类型和值的能力。在Go语言中,reflect 包提供了反射功能。通过反射,我们可以获取一个接口值(interface{})所表示的具体类型信息,以及该类型的值。

二、反射的基本用法

  1. 获取类型信息: 使用 reflect.TypeOf() 函数可以获取一个值的类型信息。
x := 42
t := reflect.TypeOf(x)
fmt.Println(t) // 输出: int
  1. 获取值信息: 使用 reflect.ValueOf() 函数可以获取一个值的反射对象,然后可以进一步获取或修改该值。
v := reflect.ValueOf(x)
fmt.Println(v.Int()) // 输出: 42
  1. 调用方法: 通过反射对象的 MethodByName() 方法,我们可以调用一个对象的方法。
type MyStruct struct {Name string
}func (m *MyStruct) SayHello() {fmt.Println("Hello, my name is", m.Name)
}ms := &MyStruct{Name: "Alice"}
method := reflect.ValueOf(ms).MethodByName("SayHello")
method.Call(nil) // 输出: Hello, my name is Alice
  1. 其他:
type Student struct {Id   int64Name stringAge  int
}func TestStruct(t *testing.T) {stu := Student{1, "zs", 12}obj := reflect.ValueOf(stu)field := obj.FieldByName("Name")field1 := obj.Field(0)num := obj.NumField()fmt.Println("字段数量:", num)fmt.Println("Name字段的值:", field)fmt.Println("第0个字段的值:", field1)obj1 := reflect.ValueOf(new(Student))addr := obj1.CanAddr() //是否能寻址if addr {fmt.Println(obj1.Addr())}
}// 切片类型的反射
func TestSlice(t *testing.T) {slice := make([]int, 10)s := reflect.ValueOf(slice)//加入元素s.Index(0).Set(reflect.ValueOf(100))//获取元素i := s.Index(0).Interface()fmt.Println(slice)fmt.Println(i)
}// Map类型的反射
func TestMap(t *testing.T) {m := make(map[string]interface{})m["A"] = 1m["B"] = 2m["C"] = 3mv := reflect.ValueOf(m)//赋值mv.SetMapIndex(reflect.ValueOf("D"),reflect.ValueOf(4))iter := mv.MapRange()keys := mv.MapKeys()fmt.Println(keys)for iter.Next() {fmt.Println(iter.Value())}
}func TestReflection(t *testing.T) {var x float64 = 3.4v := reflect.ValueOf(x)//v.SetFloat(7.1) // Error: will panic.p:= reflect.ValueOf(&x)v1 := p.Elem()fmt.Println("settability of v:", v1.CanSet())v1.SetFloat(7.1)fmt.Println(v.Interface())fmt.Println(x)
}

三、反射的优点

  1. 灵活性: 反射允许我们在运行时动态地操作对象,这为编写通用代码和库提供了极大的便利。
  2. 调试和测试: 反射可以用于在运行时检查对象的状态,这对于调试和测试非常有用。

四、反射的潜在陷阱

  1. 性能损失: 反射操作通常比直接操作要慢得多,因为它们涉及到运行时类型信息的查找和值的间接访问。
  2. 破坏封装性: 过度使用反射可能会破坏代码的封装性,使得代码难以理解和维护。
  3. 类型安全: 由于反射允许我们绕过类型检查,因此可能导致类型错误或运行时错误。

五、何时使用反射?

虽然反射提供了强大的功能,但在大多数情况下,我们应该避免使用它。以下是一些使用反射的合理场景:

  1. 编写通用代码: 当我们需要编写处理不同类型数据的通用函数时,反射是一个很好的选择。
  2. 序列化和反序列化: 在实现自定义的序列化和反序列化逻辑时,反射可以帮助我们动态地处理不同类型的数据。
  3. 框架和库开发: 在开发框架和库时,反射可以帮助我们实现更灵活和可扩展的功能。

六、总结

Go语言的反射机制为我们提供了在运行时检查和操作对象类型和值的强大能力。然而,它也有一些潜在的陷阱和限制。因此,在使用反射时,我们需要权衡其优点和缺点,谨慎地选择何时使用它。在大多数情况下,我们应该优先使用静态类型检查和直接操作来保持代码的清晰、高效和类型安全。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/682539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI视野·今日CV 计算机视觉论文速览 第293期】Fri, 19 Jan 2024

AI视野今日CS.CV 计算机视觉论文速览 Fri, 19 Jan 2024 Totally 103 papers 👉上期速览✈更多精彩请移步主页 Daily Computer Vision Papers ParaHome: Parameterizing Everyday Home Activities Towards 3D Generative Modeling of Human-Object Interactions Aut…

PyTorch深度学习快速入门教程 - 【小土堆学习笔记】

小土堆Pytorch视频教程链接 声明: 博主本人技术力不高,这篇博客可能会因为个人水平问题出现一些错误,但作为小白,还是希望能写下一些碰到的坑,尽力帮到其他小白 1 环境配置 1.1 pycharm pycharm建议使用2020的&…

c入门第十五篇——学而时习之(阶段性总结)

古人说:“学而时习之。”古人又说:“温故而知新。”古人还说:“读书百遍,其义自见。” 总结一个道理那就是好书要反反复复的读,学习过的知识要时常去复习它,才有可能常读常新。 我:“师弟&…

蔚来面试解答

你的问题包含了多个方面,我会尽力逐一回答: 锁机制及锁膨胀过程: 锁机制是并发编程中用于控制多线程对共享资源访问的一种机制,以避免资源冲突导致的数据不一致问题。锁膨胀是指锁在运行时根据竞争情况可以升级的过程,…

【安装pytorch】

项目场景: 提示:这里简述项目相关背景: 例如:项目需求安装pytorch,安装神经网络环境配置。 问题描述 提示:这里描述项目中遇到的问题: 安装pytorch 官网 https://pytorch.org/ 详细看官方提供…

petalinux2018.3安装步骤

1、虚拟机安装ubuntu-16.04.7-desktop-amd64.iso (注意:安装ubuntu-18.04.6-desktop-amd64.iso和ubuntu-16.04.6-desktop-i386.iso会报以下错误) environment: line 314: ((: 10 #15~1 > 10 #3: syntax error in expression (error toke…

C#中使用 => 运算符的 switch 表达式

目录 一、关于switch 语句 1.switch 语句及语法结构 2.switch 语句的一些重要注意事项 3.通常情况下的示例 1.示例1 2.示例2 二、使用 > 运算符的 switch 表达式 1.关于switch表达式 2.示例1 3.示例2 一、关于switch 语句 1.switch 语句及语法结构 C# 中的 swit…

有用的 Bash 别名和函数简介

简介 随着你在命令行上的操作越来越多,你会发现你使用的大部分命令只是可用命令的一个非常小的子集。大多数任务是习惯性的,你可能每天都以相同的方式运行这些任务。 虽然许多常见命令实用程序的制造者已经尝试通过使用缩短的名称(想想每天…

【Springboot】参数校验 spring-boot-starter-validation

# 第一步&#xff1a;引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>xxx</version> </dependency> # 第二步&#xff1a;实体类添加…

Excel

1、Excel的学习路径 2、掌握excel的基础要求 01、保证新版本 02、培养好的数据表格习惯 03、主动性探索 04、多联系 一、函数 二、文本清洗函数 三、常见文本的清洗函数 获取k的位置 FIND("k",P2,1) 从第1个位置开始在位置P2&#xff0c;查询字段k&#x…

Java+SpringBoot+Vue:高校科研管理的技术革新

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

ChatGPT高效提问—prompt实践(智能开发)

ChatGPT高效提问—prompt实践&#xff08;智能开发&#xff09; ​ 如果你是一名程序员&#xff0c;一定有过这样的经历&#xff1a;排查某个bug话费好几个小时&#xff0c;在各个搜索引擎尝试搜索&#xff0c;浏览了几十甚至上百个网站&#xff0c;结果搜到的答案千篇一律&am…

websocket简易基操

一、概述 1.1 简介 WebSocket是HTML5下一种新的协议&#xff08;websocket协议本质上是一个基于tcp的协议&#xff09;&#xff0c;它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和带宽并达到实时通讯的目的&#xff0c;Websocket是一个持久化的协议。…

【STM32 CubeMX】GPIO的工作模式

文章目录 前言一、有哪些工作模式&#xff1f;1.1 GPIO的详细介绍1.2 GPIO的内部框图输入模式输出部分 总结 前言 在嵌入式系统开发中&#xff0c;对于STM32微控制器的GPIO&#xff08;General Purpose Input/Output&#xff09;引脚的配置和使用是至关重要的。GPIO引脚可以通…

基本算法--贪心

1.简述 贪心法的效率非常高&#xff0c;复杂度常常为O&#xff08;1&#xff09;&#xff0c;是一种局部最优的解题方法&#xff0c;而很多问题都需要求全局最优&#xff0c;&#xff0c;所以在使用贪心法之前需要评估是否能从局部最优推广到全局最优。 2.思路 作为算法的贪…

【解决】配置文件YAML: application.yml Cannot resolve configuration property ‘xxxx‘

配置文件YAML: application.yml Cannot resolve configuration property xxxx 问题排查解决 问题 在application.yml文件里面配置Bean的初始值&#xff0c;但是报错如下&#xff1a; Cannot resolve configuration property person.lastName 排查 我们先去Bean检查是否拼写…

【国产MCU】-CH32V307-通用定时器(GPTM)-输入捕获模式测量脉冲

通用定时器(GPTM)-输入捕获模式测量脉冲 文章目录 通用定时器(GPTM)-输入捕获模式测量脉冲1、通用定时器(GPTM)介绍2、输入捕获模式3、驱动API介绍4、定时器输入捕获示例CH32V307的通用定时器模块包含一个16 位可自动重装的定时器(TIM2、TIM3、TIM4和TIM5),用于测量脉…

C语言函数的实参与形参

概念&#xff1a; 函数调用中的参数&#xff0c;被称为实参&#xff0c;即 arguments函数定义中的参数&#xff0c;被称为形参&#xff0c;即 parameters 实参与形参的关系&#xff1a; 实参于形参的类型和个数必须一一对应。形参的值由实参初始化。形参与实参位于不同的内存区…

基于函数计算AIGC图片识别

目录 在 OSS 中建立图片目录 在函数计算中基于模板创建ImageAI应用 体验ImageAI图像识别效果 我们不但可以基于函数计算创建AIGC应用&#xff0c;实现以文生图&#xff0c;同时我们也可以基于函数计算创建ImageAI应用&#xff0c;通过简单几步实现对图片中对象的识别。下面我…

【运维测试】测试理论+工具总结笔记第1篇:测试理论的主要内容(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论测试理论测试工具相关知识。Python测试理论的主要内容&#xff0c;掌握软件测试的基本流程&#xff0c;知道软件测试的V和W模型的优缺点&#xff0c;掌握测试用例设计的要素&#xff0c;掌握等价类划分法、边界值法、因…