【Go语言快速上手(六)】管道, 网络编程,反射,用法讲解

news2024/10/6 1:35:02

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:Go语言专栏⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习更多Go语言知识
  🔝🔝


在这里插入图片描述

GO快速上手

  • 1. 前言
  • 2. 初识管道
  • 3. 管道的高级用法
  • 4. GO中的网络编程
  • 5. GO语言中的反射
  • 6. 总结以及拓展

1. 前言

本篇文章是GO语言快速上手系列的最后一篇文章, 学完本章后你就掌握了GO语言常用的所有知识和语法, 在未来使用GO语言时你可能还会遇见一些奇怪的语法,但是别害怕, GO就是为了简洁而生,你有Java或CPP的基础,学什么都很快的

本章重点:

本篇文章着重讲解GO中的管道的概念以及用法. 还会讲解GO语言是怎样实现网络编程的, 会通过一个例子来讲解. 最后会讲解GO语言的反射机制,以及反射的语法.由于GO语言没有传统意义上的泛型编程概念,所以学习反射还是有必要的


2. 初识管道

说白了管道就是一个数据结构: 队列

在这里插入图片描述

管道的定义:

var 变量名 chan 管道类型
var channel chan int
管道可通过make进行初始化
channel = make(chan int,3)//管道可以存放三个int类型变量

管道是有类型的,int类型管道只能写入int类型数据,并且管道是引用类型,必须初始化后,即make后才能使用它.除此之外,管道的用法比较奇特,通过左箭头<-来向管道存放或取出数据

var intchan chan int = make(chan int,3)
//向管道中存放数据
intchan<-10
intchan<-20
num := 30
intchan<-num
//从管道中取出数据
data1 := <-intchan
data2 := <-intchan
data3 := <-intchan

显而易见,插入管道的顺序为10,20,30,所以取出数据时,data123分别对应10,20,30. 并且从管道中取出数据的意思就是把它拿出来. 除此之外,使用范围for进行遍历时,打印出数据后, 管道中的数据也会被取出.

var intchan chan int = make(chan int,3)
//向管道中存放数据
intchan<-10
intchan<-20
num := 30
intchan<-num
for v:= range intchan{
	fmt.Println("value: ",v)
}

管道的for-range循环只有value,没有key,并且如果你直接这样写代码,会报错, 因为for-range会一直遍历管道,并不会在乎管道中是否还存在数据. 所以在使用for-range之前应该先用close函数将管道关闭

  • 不关闭管道, for-range会一直取数据
  • 关闭管道后, 不可写入,但可读取

3. 管道的高级用法

管道可以声明为只读或只写性质:

var intchan1 chan<- int //只写
var intchan2 <-chan int //只读

除此之外,如果你学过多路转接select,那么这对于你来说应该很轻松.当有多个管道时,需要解决选择问题,select的作用就是在多个管道中随机公平的选择一个来执行.这是通过select和case来实的,case后面必须进行IO操作,不能是等值, 随机去选取一个IO操作.若select时迟迟没有管道就绪,那么就会一直阻塞在select处.加上default语句,可以避免这种阻塞发生

package main

import (
	"fmt"
	"time"
)
func main() {
	intchan1 := make(chan int, 10)
	intchan2 := make(chan string, 10)
	intchan3 := make(chan float32, 10)
	go func() {//匿名函数
		time.Sleep(time.Second * 5)
		intchan1 <- 10
	}()
	go func() {
		time.Sleep(time.Second * 4)
		intchan2 <- "zbcdefg"
	}()
	go func() {
		time.Sleep(time.Second * 3)
		intchan3 <- 3.14
	}()
	select {
	case v1 := <-intchan1:
		fmt.Printf("intchan1: %v", v1)
	case v2 := <-intchan2:
		fmt.Printf("intchan2: %v", v2)
	case v3 := <-intchan3:
		fmt.Printf("intchan3: %v", v3)
	default:
		fmt.Println("防止select被阻塞")
	}
}

在这里插入图片描述


4. GO中的网络编程

GO语言有net包直接进行网络编程,十分的方便,不像CPP一样进行网络编程时需要调用系统调用来完成.话不多说,直接上手代码示例:

服务器端:

  1. 监听一个地址和端口

  2. 接受客户端的连接

  3. 读取和写入数据

package main  
import (  
    "bufio"  
    "fmt"  
    "net"  
    "os"  
)  
func main() {  
    // 监听TCP端口  
    listener, err := net.Listen("tcp", ":8080")  
    if err != nil {  
        fmt.Println(err)  
        return  
    }  
    defer listener.Close()  
    for {  
        // 接受新的连接  
        conn, err := listener.Accept()  
        if err != nil {  
            fmt.Println(err)  
            continue  
        }  
        //到来连接时,让协程去执行读写操作
        go handleRequest(conn) // 使用goroutine处理连接  
    }  
}  

func handleRequest(conn net.Conn) {  
    defer conn.Close()  
    // 读取数据  
    reader := bufio.NewReader(conn)  
    message, err := reader.ReadString('\n')  
    if err != nil {  
        fmt.Println(err)  
        return  
    }  
    fmt.Print("Message received: ", string(message))  
    // 发送数据  
    conn.Write([]byte("Message received!\n"))  
}

如果你清楚TCP通信的基本流程,那么你一定知道,net.Listen函数就是封装了系统调用listen,而方法listener.Accept封装了系统调用accept,返回的conn也就是就绪的连接fd

客户端:

  1. 连接到服务器

  2. 读取和写入数据

package main  
import (  
    "bufio"  
    "fmt"  
    "net"  
    "os"  
)  
func main() {  
    // 连接到TCP服务器  
    conn, err := net.Dial("tcp", "127.0.0.1:8080")  
    if err != nil {  
        fmt.Println(err)  
        return  
    }  
    defer conn.Close()  
    // 发送数据  
    fmt.Fprintf(conn, "Hello, Server!\n")  
    // 读取响应  
    reader := bufio.NewReader(conn)  
    message, err := reader.ReadString('\n')  
    if err != nil {  
        fmt.Println(err)  
        return  
    }  
    fmt.Print("Message from server: ", string(message))  
}

对Linux熟悉的同学一眼就能看出,这个fprintf就是向文件描述符conn中输入数据的,都是封装了C,所以说我建议学GO语言要先把基础知识打牢固


5. GO语言中的反射

GO不直接支持泛型编程,但通过反射可以弥补这一缺陷,话不多说,直接上概念:

在这里插入图片描述
代码示例:

func test(i interface{}){
	//1.调用typeof函数,返回reflect.Type类型数据
	reType := reflect.TypeOf(i)
	fmt.Println(reType)
	//2. 调用valueof函数,返回reflect.value类型数据
	reValue := reflect.ValueOf(i)
	fmt.Println(reValue)
	//注,revalue是valueof类型,不能直接进行运算
	//想要获取revalue的值要调用revalue.Int()方法
}

func main(){
	//对基本类型进行反射
	var num int = 100
	test(num)
}

反射要通过传递空接口来实现,不知各位是否还记得在讲接口时说到,任意类型都实现的空接口,也就是说任意类型的变量都可以传递给空接口,接口和reflect.value类型可以相互转换,转换关系如下:

在这里插入图片描述

获取变量的类别有两种方式:

reflect.Type.kind()
reflect.Value.kind()

注意,类别和类型是两种概念,类别是指bool,int,int32,int64,struct,map这种大分类,而变量的类型是小分类. 除此之外,还可以对结构体类型进行反射:

func test(i interface{}){
	//1.调用typeof函数,返回reflect.Type类型数据
	reType := reflect.TypeOf(i)
	fmt.Println(reType)
	//2. 调用valueof函数,返回reflect.value类型数据
	reValue := reflect.ValueOf(i)
	fmt.Println(reValue)
	fmt.Println(reType.kind())
}

type stu struct{
	Name string
	Age int
}

func main(){
	//对结构体类型进行反射
	student := stu{
		Name : "张三"
		Age : 18
	}
	test(student)
}

在这里插入图片描述

更多关于反射的使用手册,大家可以自行问GPT


6. 总结以及拓展

GO语言快速上手这一系列的文章就结束了,但GO语言的学习之旅还远远没有结束, 本系统文章只讲解了很常用的GO语法,在实际生产生活中,如果遇见了诸如像context类型的新概念,大家可以自行去学习,感谢您的阅读,再见

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

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

相关文章

自定义SpringBoot的starter

案例需求&#xff1a;自定义redis-stater。要求当导入redis坐标时&#xff0c;SpringBoot自动创建Jedis的Bean。 实现步骤&#xff1a; 1、创建redis-spring-boot-autoconfigure模块 2、创建redis-spring-boot-starter模块&#xff0c;依赖redis-spring-boot-autoconfigure的…

Codeforces Round 938 (Div. 3)H-The Most Reckless Defense

来源 题目 You are playing a very popular Tower Defense game called "Runnerfield 2". In this game, the player sets up defensive towers that attack enemies moving from a certain starting point to the players base. You are given a grid of size nm&a…

Delta lake with Java--利用spark sql操作数据2

上一篇文章尝试了建库&#xff0c;建表&#xff0c;插入数据&#xff0c;还差删除和更新&#xff0c;所以在这篇文章补充一下&#xff0c;代码很简单&#xff0c;具体如下&#xff1a; import org.apache.spark.sql.SaveMode; import org.apache.spark.sql.SparkSession;publi…

DRF中的请求入口分析及request对象分析

DRF中的请求入口分析及request对象分析 django restframework框架是在django的基础上又给我们提供了很多方便的功能&#xff0c;让我们可以更便捷基于django开发restful API 1 drf项目 pip install django pip install djangorestframework1.1 核心配置 INSTALLED_APPS [d…

【源码阅读】Golang中的go-sql-driver库源码探究

文章目录 前言一、go-sql-driver/mysql1、驱动注册&#xff1a;sql.Register2、驱动实现&#xff1a;MysqlDriver3、RegisterDialContext 二、总结 前言 在上篇文章中我们知道&#xff0c;database/sql只是提供了驱动相关的接口&#xff0c;并没有相关的具体实现&#xff0c;具…

PG数据库结构与oracle比较

1.数据库集簇逻辑结构 数据库集簇概念&#xff1a;一个大的数据库是由若干个小的数据库组成&#xff0c;实现数据的隔离存放&#xff0c;在概念上应该是与mysql一样的 在mysql中可以用show database列出数据库 PG中用\l 数据库对象存放在数据库中&#xff1a; PG中的所有数据…

Mac 上安装多版本的 JDK 且实现 自由切换

背景 当前电脑上已经安装了 jdk8; 现在再安装 jdk17。 期望 完成 jdk17 的安装&#xff0c;并且完成 环境变量 的配置&#xff0c;实现自由切换。 前置补充知识 jdk 的安装路径 可以通过查看以下目录中的内容&#xff0c;确认当前已经安装的 jdk 版本。 cd /Library/Java/Java…

Maven3.9.6下载安装教程

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ &#x1f440;&#x1f440;&#x1f440; 个人博客&#xff1a;小奥的博客 &#x1f44d;&#x1f44d;&#x1f44d;&#xff1a;个人CSDN ⭐️⭐️⭐️&#xff1a;Github传送门 &#x1f379; 本人24应届生一枚&#xff0c;技术和水平有…

Typescript精进:前端必备的5大技巧(AI写作)

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

瑞_23种设计模式_解释器模式

文章目录 1 解释器模式&#xff08;Interpreter Pattern&#xff09;1.1 介绍1.2 概述1.2.1 文法&#xff08;语法&#xff09;规则1.2.2 抽象语法树 1.3 解释器模式的结构1.4 解释器模式的优缺点1.5 解释器模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代…

【右一的开发日记】全导航,持续更新...

文章目录 &#x1f4da;前端【跟课笔记】&#x1f407;核心技术&#x1f407;高级技术 &#x1f4da;捣鼓捣鼓&#x1f407;小小案例&#x1f407;喵喵大王立大功&#x1f407;TED自用学习辅助网站&#x1f407;世界top2000计算机科学家可视化大屏&#x1f407;基于CBDB的唐代历…

【Java EE】MyBatis使用注解操作数据库

文章目录 &#x1f340;参数传递&#x1f334;增(Insert)&#x1f338;返回主键 &#x1f343;删(Delete)&#x1f333;改(Update)&#x1f332;查(Select)&#x1f338;起别名&#x1f338;结果映射&#x1f338;开启驼峰命名(推荐) ⭕总结 &#x1f340;参数传递 需求: 查找…

【JavaEE】进程的概念

文章目录 1、什么是进程&#xff08;Process&#xff09;2、PCB1.pid进程的id/标识符2.内存指针3.文件描述符表4、进程调度4.1状态4.2优先级4.3上下文4.4记账信息 1、什么是进程&#xff08;Process&#xff09; 一个程序&#xff0c;运行起来/跑起来&#xff0c;在操作系统中…

Delta lake with Java--利用spark sql操作数据1

今天要解决的问题是如何使用spark sql 建表&#xff0c;插入数据以及查询数据 1、建立一个类叫 DeltaLakeWithSparkSql1&#xff0c;具体代码如下&#xff0c;例子参考Delta Lake Up & Running第3章内容 import org.apache.spark.sql.SaveMode; import org.apache.spark.…

Ollamallama

Olllama 直接下载ollama程序&#xff0c;安装后可在cmd里直接运行大模型&#xff1b; llama 3 meta 开源的最新llama大模型&#xff1b; 下载运行 1 ollama ollama run llama3 2 github 下载仓库&#xff0c;需要linux环境&#xff0c;windows可使用wsl&#xff1b; 接…

面试:Spring(IOC、AOP、事务失效、循环引用、SpringMVC、SpringBoot的自动配置原理、Spring框架常见注解)

目录 一、Spring的单例Bean是否是线程安全的&#xff1f; 二、什么是AOP 1、介绍 &#xff08;1&#xff09;记录操作日志 &#xff08;2&#xff09;实现Spring中的事务 三、spring中事务失效的场景有哪些&#xff1f; 1、异常捕获处理 2、抛出检查异常 3、非public方…

ElasticSearch教程入门到精通——第四部分(基于ELK技术栈elasticsearch 7.x新特性)

ElasticSearch教程入门到精通——第四部分&#xff08;基于ELK技术栈elasticsearch 7.x新特性&#xff09; 1. Elasticsearch进阶1.1 核心概念1.1.1 索引Index1.1.1.1 索引创建原则1.1.1.2 Inverted Index 1.1.2 类型Type1.1.3 文档Document1.1.4 字段Field1.1.5 映射Mapping1.…

【Mac】Mac安装软件常见问题解决办法

前言 刚开始用Mac系统的小伙伴或者在更新系统版本后运行App的朋友会经常碰到弹窗提示「xxx已损坏&#xff0c;无法打开&#xff0c;您应该将它移到废纸篓」、「打不开xxx&#xff0c;因为Apple无法检查其是否包含恶意软件」、「打不开xxx&#xff0c;因为它来自身份不明的开发…

模型训练中的过拟合和欠拟合

基本概念 我们知道&#xff0c;所谓的神经网络其实就是一个复杂的非线性函数&#xff0c;网络越深&#xff0c;这个函数就越复杂&#xff0c;相应的表达能力也就越强&#xff0c;神经网络的训练则是一个拟合的过程。   当模型的复杂度小于真实数据的复杂度&#xff0c;模型表…

保存钉钉群直播回放下载:直播回放下载步骤详解

今天&#xff0c;我们就来拨开云雾&#xff0c;揭开保存钉钉群直播回放的神秘面纱。教会你们如何下载钉钉群直播回放 首先用到的工具我全部打包好了&#xff0c;有需要的自己下载一下 钉钉群直播回放工具下载&#xff1a;https://pan.baidu.com/s/1WVMNGoKcTwR_NDpvFP2O2A?p…