【启程Golang之旅】网络编程与反射

欢迎来到Golang的世界!在当今快节奏的软件开发领域,选择一种高效、简洁的编程语言至关重要。而在这方面,Golang(又称Go)无疑是一个备受瞩目的选择。在本文中,带领您探索Golang的世界,一步步地了解这门语言的基础知识和实用技巧。

目录

初识网络编程

初识反射


初识网络编程

把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。设备之间在网络中进行数据的传输,发送/接收数据。

网络:两台或者两台以上计算机就可以构成网络,如下图所示:

设备之间进行传输数据的时候,必须遵循一定的通讯协议规则,具体如下所示:

接下来我们就网络通信的流程写一下网络编程实现的过程,如下:

创建客户端:调用Dial函数实现创建客户端,示例代码如下所示:

func main() {// 打印fmt.Println("客户端启动。。。")// 调用Dial函数,参数需要指定tcp协议,需要指定服务器端的IP+PORTcon, err := net.Dial("tcp", "127.0.0.1:8888")if err != nil {fmt.Println("连接失败, err = ", err)} else {// 打印连接成功fmt.Println("连接成功, con = ", con)}
}

创建服务器端:调用Listen函数实现创建服务器端,示例代码如下所示:

func main() {// 打印fmt.Println("服务器端启动。。。")// 进行监听:需要指定服务器端TCP协议,服务器端的IP+PORTlisten, err := net.Listen("tcp", "127.0.0.1:8888")if err != nil {fmt.Println("监听失败, err = ", err)return}// 监听成功,等待客户端的连接// 循环等待客户端的连接for {con, err1 := listen.Accept()if err1 != nil {fmt.Println("等待客户端连接失败, err = ", err1)return} else {// 连接成功fmt.Printf("等待连接成功,con = %v, 接收到的客户端信息:%v \n", con, con.RemoteAddr().String())}}
}

连接测试:接下来我们开始启动我们的客户端和服务器端,这里我们首先启动服务器端,然后启动客户端对服务器端进行访问,服务器端就等待客户端的访问连接即可,画面如下所示:

发送数据:上面演示了客户端与服务器端的连接,接下来我们开始在客户端设置一些数据然后发送给服务器端,让服务器端去接收到客户端发送过来的数据,示例代码如下所示,由于客户端发送一次数据就关闭了,所以服务器端报出客户端的连接意外关闭的err,这个忽视就行。

具体的代码如下所示:

// 客户端
package mainimport ("bufio""fmt""net""os"
)func main() {// 打印fmt.Println("客户端启动。。。")// 调用Dial函数,参数需要指定tcp协议,需要指定服务器端的IP+PORTcon, err := net.Dial("tcp", "127.0.0.1:8000")if err != nil {fmt.Println("连接失败, err = ", err)} else {// 打印连接成功fmt.Println("连接成功, con = ", con)}// 通过客户端发送单行数据,然后退出reader := bufio.NewReader(os.Stdin) // os.Stdin代表终端标准输入// 从终端读取一行用户输入的信息str, err := reader.ReadString('\n')if err != nil {fmt.Println("终端输入失败, err = ", err)}// 将用户输入的信息发送给服务器端con1, err1 := con.Write([]byte(str)) // []byte将字符串转换为字节数组if err1 != nil {fmt.Println("连接失败, err = ", err1)}// 打印发送成功fmt.Printf("发送成功,发送%d个字节\n", con1)
}// 服务器端
package mainimport ("fmt""net"
)func process(con net.Conn) {// 连接数据完要进行关闭defer con.Close()for {// 创建一个切片,用于接收客户端的数据buf := make([]byte, 1024)// 接收客户端的数据n, err := con.Read(buf)if err != nil {fmt.Println("接收客户端数据失败, err = ", err)return}// 打印接收到的数据fmt.Printf("接收到客户端数据:%v \n", string(buf[0:n]))}
}func main() {// 打印fmt.Println("服务器端启动。。。")// 进行监听:需要指定服务器端TCP协议,服务器端的IP+PORTlisten, err := net.Listen("tcp", "127.0.0.1:8000")if err != nil {fmt.Println("监听失败, err = ", err)return}// 监听成功,等待客户端的连接// 循环等待客户端的连接for {con, err1 := listen.Accept()if err1 != nil {fmt.Println("等待客户端连接失败, err = ", err1)return} else {// 连接成功fmt.Printf("等待连接成功,con = %v, 接收到的客户端信息:%v \n", con, con.RemoteAddr().String())}// 准备协程,协程内容不处理客户端服务请求go process(con)}
}

初识反射

在go语言中,反射(Reflection)是指程序在运行时检查变量的类型和值,并且可以修改这些变量的值、调用其方法以及获取其字段的信息的能力。反射是一种强大的元编程工具,可以让程序在运行时动态地获取和操作类型信息,而不需要在编译时确定。在go语言中,反射是通过reflect包来实现的,以下是反射具体能做的一些事:

1)反射可以在运行时动态获取变量的各种信息,比如变量的类型,类别等信息

2)如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法)

3)通过反射,可以修改变量的值,可以调用关联的方法。

4)使用反射,需要import("reflect")

反射相关的使用函数可以通过如下的函数进行操作:

1)reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型

2)reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型(reflect.Value是一个结构体类型),通过reflect.Value,可以获取到关于该变量的很多信息。

对基本类型反射

package mainimport ("fmt""reflect"
)// 利用一个函数,函数的参数定义为空接口
func testReflect(i interface{}) {// 1.调用TypeOf()函数,返回reflect.Type类型数据reType := reflect.TypeOf(i)fmt.Println("reType: ", reType)           // reType:  intfmt.Printf("reType的具体类型是: %T \n", reType) // reType的具体类型是: *reflect.rtype// 2.调用ValueOf()函数,返回reflect.Value类型数据reValue := reflect.ValueOf(i)fmt.Println("reValue: ", reValue)        // reValue:  100fmt.Printf("reValue的具体类型是: %T", reValue) // reValue的具体类型是: reflect.Value// reValue转成空接口i2 := reValue.Interface()// 类型断言n := i2.(int)n1 := n + 30fmt.Println("n1: ", n1) // n1:  130}func main() {// 对基本数据类型进行反射var num int = 100testReflect(num)
}

这里可以通过下图深入进行了解反射:

对结构体反射

package mainimport ("fmt""reflect"
)// 利用一个函数,函数的参数定义为空接口
func testReflect(i interface{}) {// 1.调用TypeOf()函数,返回reflect.Type类型数据reType := reflect.TypeOf(i)fmt.Println("reType: ", reType)           // reType:  intfmt.Printf("reType的具体类型是: %T \n", reType) // reType的具体类型是: *reflect.rtype// 2.调用ValueOf()函数,返回reflect.Value类型数据reValue := reflect.ValueOf(i)fmt.Println("reValue: ", reValue)           // reValue:  100fmt.Printf("reValue的具体类型是: %T \n", reValue) // reValue的具体类型是: reflect.Value// reValue转成空接口i2 := reValue.Interface()// 类型断言n, flag := i2.(Student)if flag {fmt.Printf("学生的名字是:%v, 学生的年龄是: %v", n.Name, n.Age) // 学生的名字是:张三, 学生的年龄是: 18}
}// 定义学生结构体
type Student struct {Name stringAge  int
}func main() {// 对结构体反射stu := Student{Name: "张三",Age:  18,}testReflect(stu)
}

得到的结果如下所示:

如果想获取变量的类别,可以看一下如下的示例代码:

package mainimport ("fmt""reflect"
)// 利用一个函数,函数的参数定义为空接口
func testReflect(i interface{}) {// 1.调用TypeOf()函数,返回reflect.Type类型数据reType := reflect.TypeOf(i)// 2.调用ValueOf()函数,返回reflect.Value类型数据reValue := reflect.ValueOf(i)// 获取遍历的类别// (1)reTypek1 := reType.Kind()fmt.Println("reType:", k1) // reType: struct// (2)reValuek2 := reValue.Kind()fmt.Println("reValue:", k2) // reType: struct// 获取变量的类型// reValue转成空接口i2 := reValue.Interface()// 类型断言n, flag := i2.(Student)if flag { // 类型断言成功fmt.Printf("结构体的类型是: %T", n) // 结构体的类型是: main.Student}
}// 定义学生结构体
type Student struct {Name stringAge  int
}func main() {// 对结构体反射stu := Student{Name: "张三",Age:  18,}testReflect(stu)
}

反射修改变量的值:可以参考如下代码

package mainimport ("fmt""reflect"
)// 利用一个函数,函数的参数定义为空接口
func testReflect(i interface{}) {reValue := reflect.ValueOf(i)// 通过SetInt方法,将i的值设置为10reValue.Elem().SetInt(10)
}func main() {// 定义一个基本数据类型var num int = 100testReflect(&num) // 传入指针地址fmt.Println(num)  // 10
}

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

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

相关文章

Java进阶_多态特性

生活中的多态 多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作,如图所示: 现实中,比如我们按下 F1 键这个动作,同一个事件发生在不同的对象上会产生不同的结果。…

达梦8 探寻达梦排序机制之一:传统排序机制(SORT_FLAG=0)

测试版本:--03134283938-20221019-172201-20018 达梦的排序机制由四个dm.ini参数控制: SORT_BUF_SIZE 100 #maximum sort buffer size in MegabytesSORT_BLK_SIZE 1 #ma…

自动化立体库集成技术--含(思维导图)

导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 随着科技的不断进步和物流行业的快速发展,自动化立体库集成技术已成为现代物流仓储的重要支撑。 它利用先进的自动化设备和智能化管理…

[leetcode hot 150]第一百三十七题,只出现一次的数字Ⅱ

题目: 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 由于需要常数级空间和线性时间复杂度…

http协议,tomcat的作用

HTTP 概念:Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。 特点: 1.基于TCP协议:面向连接,安全 2. 基于请求-响应模型的:一次请求对应一次响应 3HTTP协议是无状态的协议:对于事务处理没有记忆能…

tsconfig.json和tsconfig.app.json文件解析(vue3+ts+vite)

tsconfig.json {"files": [],"references": [{"path": "./tsconfig.node.json"},{"path": "./tsconfig.app.json"}] }https://www.typescriptlang.org/tsconfig/#files files: 在这个例子中,files 数…

git-生成SSH密钥

git-生成SSH密钥 1 打开命令窗口2 操作 1 打开命令窗口 选择"Git Bash Here",打开Git命令窗口 2 操作 查看当前用户名称 git config user.name配置你的邮箱,“6xxxqq.com” 填写自己的邮箱 git config --global user.email "6xxxqq…

认识Java中的String类

前言 大家好呀,本期将要带大家认识一下Java中的String类,本期注意带大家认识一些String类常用方法,和区分StringBuffer和StringBuilder感谢大家收看 一,String对象构造方法与原理 String类为我们提供了非常多的重载的构造方法让…

计算机网络基础-VRRP原理与配置

目录 一、了解VRRP 1、VRRP的基本概述 2、VRRP的作用 二、VRRP的基本原理 1、VRRP的基本结构图 2、设备类型(Master,Backup) 3、VRRP抢占功能 3.1:抢占模式 3.2、非抢占模式 4、VRRP设备的优先级 5、VRRP工作原理 三…

React基础教程:react脚手架

1、create-react-app 全局安装create-react-app npm install -g create-react-app安装成功之后,通过命令create-react-app -V检查是否安装成功 创建一个项目 create-react-app my-app如果不想全局安装,可以直接使用npx,也可以实现相同的效…

小主机折腾记25

10.买了惠普光驱,想给880g5twr安装上,结果发现卡扣不对 880g5twr的卡扣更长一些,比光驱本身长一些,各位如果想买的注意擦亮眼睛,看看卡扣跟你的主机一致与否 后续在闲鱼上买了个卡扣,加邮费12块钱…… 1…

转让闲置商标别中了残标,与驰名商标近似被驳回!

前几天有个人说要购买一个闲置的已注册商标,普推商标知产老杨帮忙去联系了一下,发现这个商标是残标用不成,他是要买回来的做化妆品的,但是在3类化妆品里面化妆品的小类并没有通过初审下证。 大家转让闲置商标就要注意了&#xff0…

链表的中间结点

一、题目链接 https://leetcode.cn/problems/middle-of-the-linked-list/submissions/538121725、 二、思路 定义快慢指针,快指针一次走两步,慢指针一次走一步,最后慢指针的位置就是中间结点的位置 三、题解代码 //快慢指针,快…

带你学习Mybatis之逆向工程

逆向工程 可以针对单表自动生成MyBatis执行所需要的代码&#xff0c;包括&#xff1a;Mapper.java&#xff0c;Mapper.xml&#xff0c;实体类&#xff0c;这样可以减少重复代码的编写 <dependency> <groupId>org.mybatis.generator</groupId> …

【计算机视觉(9)】

基于Python的OpenCV基础入门——形态学操作 形态学操作腐蚀膨胀开运算闭运算梯度运算顶帽黑帽 形态学操作代码实现以及效果图 形态学操作 形态学操作是数字图像处理中的一种方法&#xff0c;用于改变和提取图像中的结构和形状信息。它基于图像的形状和大小特征&#xff0c;通过…

基于SpringBoot+Vue单位考勤系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还…

2024上海初中生古诗文大会倒计时4个多月:单选题真题和独家解析

现在距离2024年初中生古诗文大会还有4个多月时间&#xff0c;我们继续来看10道选择题真题和详细解析&#xff0c;以下题目截取自我独家制作的在线真题集&#xff0c;都是来自于历届真题&#xff0c;去重、合并后&#xff0c;每道题都有参考答案和解析。 为帮助孩子自测和练习&…

STM32F103C8移植uCOSIII并以不同周期点亮两个LED灯(HAL库方式)【uCOS】【STM32开发板】【STM32CubeMX】

STM32F103C8移植uC/OSIII并以不同周期点亮两个LED灯&#xff08;HAL库方式&#xff09;【uC/OS】【STM32开发板】【STM32CubeMX】 实验说明 将嵌入式操作系统uC/OSIII移植到STM32F103C8上&#xff0c;构建两个任务&#xff0c;两个任务分别以1s和3s周期对LED进行点亮—熄灭的…

前端渲染大量数据思路【虚拟列表】【异步机制】

当浏览器遇到性能瓶颈导致页面卡顿时&#xff0c;你会怎么处理&#xff1f;如何查找问题的原因&#xff1f; 浏览器本身自带性能检测工具&#xff0c;通常我们分析由脚本导致的页面卡顿会选择 性能&#xff08;performance&#xff09; 选项卡&#xff0c;在其中我们可以找到导…

3D Gaussian Splatting for Real-Time Radiance Field Rendering

辐射场方法最近在基于多张照片或视频进行新视角合成方面取得了革命性进展。然而&#xff0c;实现高视觉质量仍然需要耗时且计算成本高的神经网络&#xff0c;而最近的快速方法不可避免地在速度和质量之间进行了权衡。对于无界和完整的场景&#xff08;而不是孤立的物体&#xf…