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

1. 前言

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


2. 初识管道

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

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

var 变量名 chan 管道类型
var channel chan int
管道可通过make进行初始化
channel = make(chan int,3)//管道可以存放三个int类型变量
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 //只读
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被阻塞")
	}
}

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


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"))  
}
  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))  
}

5. GO语言中的反射

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

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

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)
}

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

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)
}

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

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


6. 总结以及拓展

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

05-02 20:52