# Go学习-Day10

Go学习-Day10

反射

  • 编写函数适配器,序列化和反序列话可以用到

  • 反射可以在运行时,动态获取变量的各种信息,例如类型,结构体本身的信息,修改变量的值,调用关联的方法

  • 反射是不是和映射相反?是一种逆函数?

  • 变量到空接口相互转换,空接口和reflect.value相互转换

  • 动手一下

go 复制代码
import (
	"fmt"
	"reflect"
)

func test(a interface{}) {
	b := reflect.TypeOf(a)
	fmt.Println(b)
}

func main() {
	var a int = 10
	test(a)
}
  • 打印 "int"

go 复制代码
reflect.TypeOf()//从接口获取原类型
reflect.ValueOf()//从接口获取reflect.Value类型.Int能取到具体的类型
//如果需要原类型,需要类型断言
reflect.Interface//把reflect.Value转换成空接口
  • Kind是大的种类,Type是小的类型

  • 常量在定义的时候必须初始化

  • reflect.Value.Kind返回的是常量

  • 如果传入指针类型的话(反射常常需要改变原来的值)指针类型需要.Elem方法取到值,再用.SetInt之类的方修改原来的值

go 复制代码
Value//指reflect.Value
Value.NumField()//获取字段数
Value.Field()//根据下标,获取第几个字段,返回的也是relect.Value
Tpye//指reflect.Type
Tpye.Field().Tag.Get("key")//可以获取tag,键值是结构体里面设置的例如,"json:"的key就是json,序列化反序列化的键值固定取json,其实可以自定义
Value.NumMethod()//获取方法数
Value.Method().Call(...)//获取第几个方法,然后调用
//这个顺序是按照函数名字典序排列的,Call传的是Value切片,返回的也是Value切片
//输入的时候需要定义一个Value切片,用reflect.ValueOf(xx)插入这个切片
Value.Elem().Field().SetXxx//修改字段
...FieldByName()//可以用字段名来找
Value.New()//为指针申请空间,可以通过反射来创建类型

网络编程

  • Golang的主要设计目标之一就是面向大规模的后端服务程序,网络通信是服务端程序必不可少的一部分
  • 网络编程有两种 TCP(Transmission Control Protocol) socket编程和HTTP编程(建立在前者之上)
  • 做服务器尽量少开端口,一个端口只能被一个程序监听

监听端口小Demo

  • net包提供了可以指的I/O接口

go 复制代码
package main

import (
	"fmt"
	"net"
)

func main() {

	fmt.Println("开始监听")
	//使用tcp协议,监听本机
	listen, err := net.Listen("tcp", "0.0.0.0:8888")
	if err != nil {
		fmt.Println("err=", err)
	}
	//延迟关闭
	defer listen.Close()
	//循环等待
	for {
		//等待客户端连接
		fmt.Println("等待连接...")
		//获取连接
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("err=", err)
		} else {
			fmt.Println("con=", conn)
		}
		//起一个协程为客户端服务
	}
}
  • 用telnet呼叫一下 telnet 127.0.0.1 8888

go 复制代码
开始监听
等待连接...
con= &{{0xc00010ec80}}
等待连接...
//返回

客户端

go 复制代码
conn, err := net.Dial("tcp", "ip...:端口")
//获取连接
//Dial是拨号的意思
  • 通过端口就能和对应的程序进行交流

go 复制代码
func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8888")
	if err != nil {
		fmt.Println("err=", err)
	}
	fmt.Println("连接成功conn=", conn)
}
//注意此时要开着上面的监听程序
//输出 连接成功conn= &{{0xc00010ca00}}

发送&&接收

server.go

go 复制代码
package main

import (
	"fmt"
	"net"
)

func process(conn net.Conn) {
	//连接过多不关闭的话就会导致其他连接无法成功
	defer conn.Close()

	for {
		buf := make([]byte, 512)
		//如果没有Write会停在这里,类似我们stdin输入的时候,光标会停在输入的位置
		//如果连接突然中断的话,这里会报错
		//TCP底层会定时发送消息,检查连接是否存在
		n, err := conn.Read(buf)
		if err != nil {
			fmt.Println("err=", err)
			return
			//有可能是关闭了
		}
		//字节切片要强制转换
		//buf后面的存的可能是乱七八糟的东西,注意取前n个!
		fmt.Print(string(buf[:n]))

	}
}

func main() {

	fmt.Println("开始监听")
	//使用tcp协议,监听本机
	listen, err := net.Listen("tcp", "0.0.0.0:8888")
	if err != nil {
		fmt.Println("err=", err)
	}
	//延迟关闭
	defer listen.Close()
	//循环等待
	for {
		//等待客户端连接
		fmt.Println("等待连接...")
		//获取连接
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("err=", err)
		} else {
			fmt.Println("con=", conn)
		}
		//起一个协程为客户端服务
		go process(conn)
	}
}

client.go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8888")
	if err != nil {
		fmt.Println("err=", err)
	}
	fmt.Println("连接成功conn=", conn)

	//创建标准stdin的reader
	reader := bufio.NewReader(os.Stdin)
	//读取一行
	str, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println("err=", err)
	}

	n, err := conn.Write([]byte(str))
	if err != nil {
		fmt.Println("err=", err)
	}
	fmt.Println("发送了n个字节n=", n)
}
  • 一个小点,发送的字节数多2,应该是回车键的缘故,可能这里是当成\n\r
相关推荐
摇滚侠9 分钟前
《On Java 中文版 基础卷》阅读笔记 安装 Java 和本书示例 02
java·开发语言·笔记
FfHUCisI20 分钟前
sync.Once 与 sync.Cond 源码与并发控制陷阱
服务器·开发语言·后端·golang
阿钱真强道25 分钟前
21 嵌入式操作系统 | JSON 与 json-c:生成与解析
c语言·开发语言·json·json-c
j7~25 分钟前
【Python】(篇六)《基础语法(函数、列表和元组、字典、文件)》---详解
开发语言·python·文件·函数·字典·编程学习·元组与列表
艾莉丝努力练剑33 分钟前
【AI大模型接入SDK】ChatSDK架构设计与实现
网络·c++·人工智能·学习·语言模型
重生之小比特38 分钟前
【C++进阶】红黑树的实现
java·开发语言·c++
纪念 22938 分钟前
C++算法(一)
开发语言·c++·算法
Yunovian2 小时前
AI时代,针对模型与应用,浅谈一下各编程语言
开发语言·c++·人工智能·python·ai·rust·ai编程
周杰伦fans3 小时前
构建真正智能的CAD AI绘图代理
开发语言·人工智能·c#
zhanghaha13145 小时前
Python进阶教程:35_PyQt (保姆级零基础教程)
开发语言·python·pyqt