GoLang核心知识点

目录

1. 系统中断信号注册

2. 通道接收多个返回值

3. go context

4. reflect

5. json字符串对象转换


1. 系统中断信号注册

interrupt := make(chan os.Signal) // 可以控制强制终止的信号
// 如果系统有中断信号,发送给r.interrupt
signal.Notify(interrupt, os.Interrupt)// Ctrl+C 退出
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
fmt.Printf("quit (%v)\n", <-sig)

2. 通道接收多个返回值

通道接收的多参返回,如果可以接收的话,第一参数是接收的值,第二个表示通道是否关闭,false表示通道关闭,true表示通道正常。

res := make(chan io.Closer, size)
r, ok := <- res

3. go context

func main() {ctx, cancel := context.WithCancel(context.Background())go func(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("监控退出,停止了...")returndefault:fmt.Println("goroutine监控中...")time.Sleep(2 * time.Second)}}}(ctx)time.Sleep(10 * time.Second)fmt.Println("可以了,通知监控停止")cancel()//为了检测监控过是否停止,如果没有监控输出,就表示停止了time.Sleep(5 * time.Second)}

context.Background() 返回一个空的Context,这个空的Context一般用于整个Context树的根节点。然后我们使用context.WithCancel(parent)函数,创建一个可取消的子Context,然后当作参数传给goroutine使用,这样就可以使用这个子Context跟踪这个goroutine。在goroutine中,使用select调用<-ctx.Done()判断是否要结束,如果接受到值的话,就可以返回结束goroutine了;如果接收不到,就会继续进行监控。

那么是如何发送结束指令的呢?这就是示例中的cancel函数啦,它是我们调用context.WithCancel(parent)函数生成子Context的时候返回的,第二个返回值就是这个取消函数,它是CancelFunc类型的。我们调用它就可以发出取消指令,然后我们的监控goroutine就会收到信号,就会返回结束。

使用Context控制一个goroutine的例子如上,非常简单,下面我们看看控制多个goroutine的例子,其实也比较简单。

func main() {ctx, cancel := context.WithCancel(context.Background())go watch(ctx,"【监控1】")go watch(ctx,"【监控2】")go watch(ctx,"【监控3】")time.Sleep(10 * time.Second)fmt.Println("可以了,通知监控停止")cancel()//为了检测监控过是否停止,如果没有监控输出,就表示停止了time.Sleep(5 * time.Second)
}func watch(ctx context.Context, name string) {for {select {case <-ctx.Done():fmt.Println(name,"监控退出,停止了...")returndefault:fmt.Println(name,"goroutine监控中...")time.Sleep(2 * time.Second)}}
}
  • 不要把Context放在结构体中,要以参数的方式传递
  • 以Context作为参数的函数方法,应该把Context作为第一个参数,放在第一位。
  • 给一个函数方法传递Context的时候,不要传递nil,如果不知道传递什么,就使用context.TODO
  • Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递
  • Context是线程安全的,可以放心的在多个goroutine中传递

4. reflect

func main() {u:= User{"张三",20}t:=reflect.TypeOf(u)v := reflect.ValueOf(u)fmt.Println(t, v)// 一种简单的打印变量类型和变量值的方法fmt.Printf("%T, %v", u, u)
}type User struct{Name stringAge int
}

通过反射,我们可以获取一个结构体类型的字段,也可以获取一个类型的导出方法,这样我们就可以在运行时了解一个类型的结构,这是一个非常强大的功能。

for i:=0;i<t.NumField();i++ {fmt.Println(t.Field(i).Name)
}for i:=0;i<t.NumMethod() ;i++  {fmt.Println(t.Method(i).Name)
}

假如我们想在运行中动态的修改某个字段的值有什么办法呢?一种就是我们常规的有提供的方法或者导出的字段可以供我们修改,还有一种是使用反射,这里主要介绍反射。

func main() {x:=2v:=reflect.ValueOf(&x)v.Elem().SetInt(100)fmt.Println(x)
}

因为reflect.ValueOf函数返回的是一份值的拷贝,所以前提是我们是传入要修改变量的地址。 其次需要我们调用Elem方法找到这个指针指向的值。 最后我们就可以使用SetInt方法修改值了。

以上有几个重点,才可以保证值可以被修改,Value为我们提供了CanSet方法可以帮助我们判断是否可以修改该对象。

结构体的方法我们不光可以正常的调用,还可以使用反射进行调用。要想反射调用,我们先要获取到需要调用的方法,然后进行传参调用,如下示例:

func main() {u:=User{"张三",20}v:=reflect.ValueOf(u)mPrint:=v.MethodByName("Print")args:=[]reflect.Value{reflect.ValueOf("前缀")}fmt.Println(mPrint.Call(args))}type User struct{Name stringAge int
}func (u User) Print(prfix string){fmt.Printf("%s:Name is %s,Age is %d",prfix,u.Name,u.Age)
}

MethodByName方法可以让我们根据一个方法名获取一个方法对象,然后我们构建好该方法需要的参数,最后调用Call就达到了动态调用方法的目的。

获取到的方法我们可以使用IsValid 来判断是否可用(存在)。

这里的参数是一个Value类型的数组,所以需要的参数,我们必须要通过ValueOf函数进行转换。

5. json字符串对象转换

func main() {var u Userh:=`{"name":"张三","age":15}`err:=json.Unmarshal([]byte(h),&u)if err!=nil{fmt.Println(err)}else {fmt.Println(u)}
}type User struct{Name string `name`Age int `age`
}

可以通过反射获取字段的tag

func main() {var u Usert:=reflect.TypeOf(u)for i:=0;i<t.NumField();i++{sf:=t.Field(i)fmt.Println(sf.Tag)}
}

很多时候我们的一个Struct不止具有一个功能,比如我们需要JSON的互转、还需要BSON以及ORM解析的互转,所以一个字段可能对应多个不同的Tag,以便满足不同的功能场景。Go Struct 为我们提供了键值对的Tag,来满足我们以上的需求。

func main() {var u Usert:=reflect.TypeOf(u)for i:=0;i<t.NumField();i++{sf:=t.Field(i)fmt.Println(sf.Tag.Get("json"))}}type User struct{Name string `json:"name"`Age int `json:"age"`
}

也可以设置多个key

func main() {var u Usert:=reflect.TypeOf(u)for i:=0;i<t.NumField();i++{sf:=t.Field(i)fmt.Println(sf.Tag.Get("json"),",",sf.Tag.Get("bson"))}}type User struct{Name string `json:"name" bson:"b_name"`Age int `json:"age" bson:"b_age"`
}

多个Key使用空格进行分开,然后使用Get方法获取不同Key的值。

Struct Tag可以提供字符串到Struct的映射能力,以便我们作转换,除此之外,还可以作为字段的元数据的配置,提供我们需要的配置,比如生成Swagger文档等。

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

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

相关文章

docker (CentOS,ubuntu)安装及常用命令

Docker和虚拟机一样&#xff0c;都拥有环境隔离的能力&#xff0c;但它比虚拟机更加轻量级&#xff0c;可以使资源更大化地得到应用 Client&#xff08;Docker客户端&#xff09;&#xff1a;是Docker的用户界面&#xff0c;可以接受用户命令&#xff08;docker build&#xff…

纯前端umi项目部署页面自动刷新

背景 在用户正在访问单页面网站的情况下&#xff0c;突然发布了新的版本。而由于单页面中路由特性&#xff0c;或浏览器缓存的原因&#xff0c;并不会随着路由变化而重新加载前端资源&#xff0c;此时用户浏览器所运行的脚本&#xff0c;并非是最新的代码&#xff0c;从而可能…

img标签图片未加载完成占位图

通过Css控制&#xff0c;实现加载接口下发或者网络图片时&#xff0c;未加载完成前&#xff0c;先加载本地一张占位图&#xff0c;记载完成显示接口下发的图或者网络图。 实现方式&#xff1a;通过在img标签的after伪元素上添加一张占位图&#xff0c;并且img标签都设置为posi…

记录Python的pandas库详解

如何生成一个pd import pandas as pd df pd.DataFrame([[1,2,3],[4,5,6]],index[A,B],columns[C1,C2,C3])df ---------------------------------------------------------------------------C1 C2 C3 A 1 2 3 B 4 5 6df.T -------------------------------------------------…

爬虫 新闻网站 以湖南法治报为例(含详细注释) V4.0 升级 自定义可任意个关键词查询、时间段、粗略判断新闻是否和优化营商环境相关,避免自己再一个个判断

目标网站&#xff1a;湖南法治报 爬取目的&#xff1a;为了获取某一地区更全面的在湖南法治报的已发布的和优化营商环境相关的宣传新闻稿&#xff0c;同时也让自己的工作更便捷 环境&#xff1a;Pycharm2021&#xff0c;Python3.10&#xff0c; 安装的包&#xff1a;requests&a…

element-ui container 组件源码分享

今日简单分享 container 组件的源码实现&#xff0c;从以下两个方面来讲解&#xff1a; 1、container 组件的页面结构 2、container 组件的属性 一、container 组件的页面结构 二、container 组件的属性 1、container 部分的 direction 属性&#xff0c;子元素的排列方向&am…

Nacos2.3.0安装部署

一&#xff0c;准备安装包 github下载点 二&#xff0c;在/usr/local/目录下创建一个文件夹用于上传和解压Nacos cd /usr/local/ #上传Nacos文件 #解压之前cd进安装包根目录 cd /usr/local/ #这边选择的Nacos版本为2.3.0 tar -zxxvf nacos-server-2.3.0.tar.gz #把该文件移动…

Spring Boot安装与配置

一、引言 Spring Boot是一个开源的Java框架&#xff0c;用于简化Spring应用的创建、运行和部署过程。它遵循“约定优于配置”的原则&#xff0c;使得开发者能够更专注于业务逻辑的实现&#xff0c;而非繁琐的配置。本教程将指导您完成Spring Boot的安装和配置过程&#xff0c;…

基于SpringBoot的“商务安全邮箱”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“商务安全邮箱”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构 收件箱效果图 草稿箱效果图 已发送…

【数据结构】习题之消失的数字和轮转数组

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《数据结构》 &#x1f389;前路漫漫亦灿灿 前言 消失的数字这道题目我会和大家分享三种思路。 还有一道题目是轮转数组&#xff0c;&#xff0c;也会分享三种思路&#xff0c;大…

常见的垃圾回收器(下)

文章目录 G1ShenandoahZGC 常见垃圾回收期&#xff08;上&#xff09; G1 参数1&#xff1a; -XX:UseG1GC 打开G1的开关&#xff0c;JDK9之后默认不需要打开 参数2&#xff1a;-XX:MaxGCPauseMillis毫秒值 最大暂停的时间 回收年代和算法 ● 年轻代老年代 ● 复制算法 优点…

Methoxy PEG Propionic acid具有良好的亲水性和分子量可控性

【试剂详情】 英文名称 mPEG-PA&#xff0c;mPEG-Propionic acid&#xff0c; Methoxy PEG PA&#xff0c; Methoxy PEG Propionic acid 中文名称 聚乙二醇单甲醚丙酸&#xff0c; 甲氧基-聚乙二醇-丙酸 外观性状 由分子量决定&#xff0c;固体或者液体 分子量 400&…

如何提高直线模组的技术水平?

在工业制造业中&#xff0c;不管我们使用任何机械产品&#xff0c;都有一个共同的出发点&#xff0c;就是能用先进的技术突破其产品的性能及使用性。那么直线模组究竟是用什么技术突破其产品的使用性的呢&#xff1f; 1、优化机械设计&#xff1a;设计过程中应充分考虑模组的结…

JetBrains2024来袭

JetBrains2024来袭&#xff0c;激活包含在内的编程IDE&#xff0c;其中AppCode已下架&#xff0c;Aqua&#xff0c;RustRover不支持本地激活需要关联帐号。 Tap&#xff1a;激活稳定可靠&#xff0c;支持Windows&#xff0c;macOS&#xff0c;Linux客户端。

使用django model 建立一个机房巡检记录表

作为一名it管理人员,日常工作中的一项就是巡检机房了,通常需要记录到本子上,或者说叫登记表。 from django.db import modelsclass InspectionRecord(models.Model):STATUS_CHOICES = ((正常, 正常),(异常

阿里云大学考试python中级题目及解析-python中级

阿里云大学考试python中级题目及解析 1.WEB开发中&#xff0c;下列选项中能够实现客户端重定向的设置是&#xff08;&#xff09; A.响应头设置Location状态码200 B.响应头设置Location状态码302 C.响应头设置Accept-Location状态码301 D.响应头设置Accept-Location状态码…

C语言【指针】

1. 基本语法 1.1 指针变量的定义和使用(重点) 指针是一种数据类型&#xff0c;指针变量指向谁 就把谁的地址赋值给指针变量 1.2 通过指针间接修改变量的值 指针变量指向谁 就把谁的地址赋值给指针变量 可以通过 *指针变量 间接修改变量的值 1.3 const修饰的指针变量 语法…

全视通院内导航助力“医”路畅通,让您就医不迷路

“这个科室怎么走&#xff1f;”“CT检查在哪里做&#xff1f;”“请问抽血在哪里&#xff1f;”…… 这是患者在赴院就诊时常会发出的疑问&#xff0c;医院导诊台及其他区域的工作人员对此应接不暇&#xff0c;繁忙时段更容易顾此失彼&#xff0c;不仅自身工作负担大&#xf…

stable diffusion基本原理

diffusion model latent diffusion &#xff1a;先对图片降维&#xff0c;然后在降维空间做diffusion&#xff1b;stable diffusion即基于此方法实现的&#xff0c;因此计算量很小&#xff1b; 共用降噪网络U-Net&#xff1a;输入noisy imagestep&#xff0c;告诉网络当前的噪声…

scipy.signal.cwt, pywt.cwt, ssq_cwt 使用记录

scipy.signal.cwt 该代码中widths以及freq计算公式来源于scipy.signal.morlet2函数官方案例 from scipy.signal import morlet, morlet2 from scipy import signal import matplotlib.pyplot as pltsignal_length 2000 fs 1000# 生成信号数据 time np.arange(0, signal_leng…