1.Go网络编程
客户端:
package client
import (
"fmt"
"net"
)
func main() {
fmt.Println("客户端启动---")
dial, err := net.Dial("tcp", "127.0.0.1:8888")
if err != nil {
fmt.Println("err ==> ", err)
return
}
fmt.Println("dial ==> ", dial)
}
服务端:
package server
import (
"fmt"
"net"
)
func main() {
fmt.Println("服务端启动---")
listen, err := net.Listen("tcp", "127.0.0.1:8888")
if err != nil {
fmt.Println("监听失败---")
}
//监听成功,等待客户端的连接
for {
listen, err := listen.Accept()
if err != nil {
fmt.Println("客户端连接失败---")
} else {
//连接成功,输出客户端信息
fmt.Println("客户端连接成功")
fmt.Println("listen ==> ", listen.RemoteAddr().String())
}
}
}
测试:
先启动服务端,服务端处于监听状态
(1)启动服务端
(2)启动客户端
服务端与客户端之间的数据传输:
输入:
客户端:
package main
import (
"bufio"
"fmt"
"net"
"os"
)
func main() {
fmt.Println("客户端启动---")
dial, err := net.Dial("tcp", "127.0.0.1:8888")
if err != nil {
fmt.Println("err ==> ", err)
return
}
fmt.Println("dial ==> ", dial)
//从终端中获取输入
readString, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
fmt.Println("err ==> ", err)
}
//将从终端中获取的数据发送给服务器
n, err := dial.Write([]byte(readString))
if err != nil {
fmt.Println("err ==> ", err)
}
fmt.Printf("发送了 %d 条数据", n)
}
服务端:
package main
import (
"fmt"
"net"
)
func process(listen net.Conn) {
//连接关闭
defer listen.Close()
for {
bytes := make([]byte, 1024)
n, err := listen.Read(bytes)
if err != nil {
return
}
if n == 0 {
fmt.Println("read 0 bytes")
}
fmt.Println(string(bytes[:n]))
}
}
func main() {
fmt.Println("服务端启动---")
listen, err := net.Listen("tcp", "127.0.0.1:8888")
if err != nil {
fmt.Println("监听失败---")
}
//监听成功,等待客户端的连接
for {
listen, err := listen.Accept()
if err != nil {
fmt.Println("客户端连接失败---")
} else {
//连接成功,输出客户端信息
fmt.Println("客户端连接成功")
fmt.Println("listen ==> ", listen.RemoteAddr().String())
}
go process(listen)
}
}
2.反射
基本数据类型的反射
通过空接口确定 数值的 数值类型
输入:
package main
import (
"fmt"
"reflect"
)
func testReflect(i interface{}) {
typeOf := reflect.TypeOf(i) //返回 reflect.Type类型的数据(不能当普通的数据类型用)
valueOf := reflect.ValueOf(i) //返回 reflect.Value类型的数据(不能当普通的数值用,例如:10+valueOf)
//可通过Int()方法,获取valueOf的符号数
fmt.Println(10 + valueOf.Int())
fmt.Println(typeOf)
fmt.Println(valueOf)
}
func main() {
num := 100
//空接口中没有任何方法,可以视为任何数据类型都实现了空接口
testReflect(num)
}
输出:
110
int
100
Interface()方法
输入:
package main
import (
"fmt"
"reflect"
)
func testReflect(i interface{}) {
valueOf := reflect.ValueOf(i) //返回 reflect.Value类型的数据(不能当普通的数值用,例如:10+valueOf)
//可通过Int()方法,获取valueOf的符号数
fmt.Println(10 + valueOf.Int())
fmt.Println(valueOf)
//反射后返回原来数据
a := valueOf.Interface()
i2 := a.(int) // 断言
fmt.Println(i2 + 100)
}
func main() {
num := 100
//空接口中没有任何方法,可以视为任何数据类型都实现了空接口
testReflect(num)
}
输出:
110
100
200
3.结构体的反射
输入:
package main
import (
"fmt"
"reflect"
)
func testReflect(i interface{}) {
valueOf := reflect.ValueOf(i) //返回 reflect.Value类型的数据(不能当普通的数值用,例如:10+valueOf)
//获取valueOf的符号数
fmt.Println("valueOf ==> ", valueOf)
//反射后返回原来数据
a := valueOf.Interface()
i2, flag := a.(Person) // 断言
if flag {
fmt.Println("i2 ==> ", i2)
}
}
type Person struct {
Name string
Age int
}
func main() {
person := Person{
Name: "xx",
Age: 20,
}
//结构体实现了空接口
testReflect(person)
}
输出:
valueOf ==> {xx 20}
i2 ==> {xx 20}
4.Kind()方法的使用
获取变量的类别
使用Kind()方法返回值是一个常量
输入:
package main
import (
"fmt"
"reflect"
)
func testReflect(i interface{}) {
typeOf := reflect.TypeOf(i)
fmt.Println("i 的类型为 ==> ", typeOf)
valueOf := reflect.ValueOf(i) //返回 reflect.Value类型的数据(不能当普通的数值用,例如:10+valueOf)
//获取valueOf的符号数
fmt.Println("valueOf ==> ", valueOf)
kind := typeOf.Kind()
fmt.Println("typeOf.Kind() ==> ", kind)
k := valueOf.Kind()
fmt.Println("valueOf.Kind() ==> ", k)
}
type Person struct {
Name string
Age int
}
func main() {
person := Person{
Name: "xx",
Age: 20,
}
//结构体实现了空接口
testReflect(person)
}
输出:
i 的类型为 ==> main.Person
valueOf ==> {xx 20}
typeOf.Kind() ==> struct
valueOf.Kind() ==> struct
4.操作反射值
操作基本数据类型的值:
输入:
package main
import (
"fmt"
"reflect"
)
func testReflect(i interface{}) {
valueOf := reflect.ValueOf(i) //返回 reflect.Value类型的数据(不能当普通的数值用,例如:10+valueOf)
//获取指针指向的对象valueOf.Elem()
valueOf.Elem().SetInt(100)
fmt.Println("valueOf ==> ", valueOf)
}
func main() {
var num int = 10
testReflect(&num)
fmt.Println("num ==> ", num)
}
输出:
valueOf ==> 0xc00000a0a8
num ==> 100
操作结构体的属性和方法:
输入:
package main
import (
"fmt"
"reflect"
)
type Stdent struct {
Name string
Age int
}
// 定义方法
func (s Stdent) Dprint() {
fmt.Println("name ==> :", s.Name)
fmt.Println("age ==> :", s.Age)
}
func (s Stdent) AgetStuName() string {
return s.Name
}
func (s Stdent) BgetStuAge() int {
return s.Age
}
func (s Stdent) CsetStu(name string, age int) {
fmt.Println("调用CsetStu")
fmt.Println("name ==> :", name)
fmt.Println("age ==> :", age)
}
// 获取反射结构
func getStuStr(i interface{}) {
valueOf := reflect.ValueOf(i)
fmt.Println("valueOf ==> :", valueOf)
//获取结构体中有多少个字段
n1 := valueOf.NumField()
fmt.Println("字段数n1 ==> :", n1)
//通过循环获取具体字段值
for i := 0; i < n1; i++ {
fmt.Printf("第%v个字段的值为%v\n", i, valueOf.Field(i))
}
//获取结构体中有多少个方法
n2 := valueOf.NumMethod()
//注意这里,如果结构体的方法首字母为小写这里获取不到
fmt.Println("方法数n2 ==> :", n2)
//调用第n个方法
//注意这里方法的顺序是按照首字母ASCII码的顺序排列的
valueOf.Method(3).Call(nil) //调用Dprint()
/**
调用Call()方法
func (v Value) Call(in []Value) []Value
需要传参数时,in []Value(传入切片)
*/
//定义切片
var values []reflect.Value
values = append(values, reflect.ValueOf("xxxxxxx"))
values = append(values, reflect.ValueOf(1000))
valueOf.Method(2).Call(values)
}
func main() {
stdent := Stdent{
Name: "xx",
Age: 100,
}
getStuStr(stdent)
}
输出:
valueOf ==> : {xx 100}
字段数n1 ==> : 2
第0个字段的值为xx
第1个字段的值为100
方法数n2 ==> : 4
name ==> : xx
age ==> : 100
调用CsetStu
name ==> : xxxxxxx
age ==> : 1000
5.改变变量的值
输入:
package main
import (
"fmt"
"reflect"
)
type Stdent struct {
Name string
Age int
}
func getStuStr(i interface{}) {
valueOf := reflect.ValueOf(i)
//注意Elem()方法不能少
valueOf.Elem().Field(0).SetString("ccc")
}
func main() {
stdent := Stdent{
Name: "xx",
Age: 100,
}
fmt.Println(stdent)
getStuStr(&stdent) //注意传地址
fmt.Println(stdent)
}
输出:
{xx 100}
{ccc 100}