服务端:
服务端程序,在8888端口监听
可以和多个客户端创建链接
链接成功后,客户端发送数据,服务端接收数据并显示在终端上
客户端:
客户端程序,能连接到服务器端的8888端口
客户端可以发送单行数据,然后退出
能通过终端输入数据(输入一行发送一行),并发送给服务器端

//server.go
package main

import (
	"fmt"
	"net"
)

func process(conn net.Conn) {
	defer conn.Close() //关闭链接,不关闭则会导致链接未释放
	//循环接收客户端发送数据
	for {
		buf := make([]byte, 1024) //创建一个新的切片
		//如果对方没有read我们则会一直在等
		//等待客户端通过conn发送信息
		//如果客户端没有write[发送],那么协程就阻塞在这
		fmt.Println("等待客户端发送数据")
		n, err := conn.Read(buf) //从conn读取这个n非常重要
		//它底层每隔一段时间发送一次请求给客户端,判断客户端是否异常退出

		fmt.Println("服务器等待客户端发送数据" + conn.RemoteAddr().String())
		if err != nil { //判断条件也可以写 err == io.EOF
			fmt.Println("服务器的Read出错 err=", err)
			return
		}
		//显示客户端发送的内容到服务器的终端
		/*
			这里不能够使用Println,因为我们在客户端通过判断\n来结束,如果用println会多一行
			这个是把buf字节转为string,这个n非常重要,如果不带n会导致把后面1024个数据全部读到
		*/
		fmt.Print(string(buf[:n]))

	}
}
func main() {
	fmt.Println("服务器开始监听")
	listen, err := net.Listen("tcp", "localhost:8888")
	defer listen.Close()
	if err != nil {
		fmt.Println("listen err=", err)
		return
	}
	//循环等待客户端链接
	for {
		//等待客户端链接
		fmt.Println("等待客户端链接...")
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("accept err=", err)
		} else {
			fmt.Printf("accept, con=%v 客户端ip=%v\n", conn, conn.RemoteAddr().String())
		}
		//这里起一个协程,服务客户端
		go process(conn)
	}
}
//client.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)
		return
	}
	//功能一,客户端发送单行数据,然后输出
	reader := bufio.NewReader(os.Stdin)

	//从终端读取一行用户输入并准备发送给服务器
	line, err := reader.ReadString('\n') //返回一个字符串
	if err != nil {
		fmt.Println("radString err=", err)
	}
	//再将line 发送给服务器
	n, err := conn.Write([]byte(line)) //可能存在丢包和网络阻塞
	if err != nil {
		fmt.Println("conn.Write err=", err)
	}
	fmt.Printf("客户端发送了 %d 的数据,退出", n)
}

程序拓展,让客户端能多次输入数据(输入一行发送一行),并发送给服务端
在终端输入exit表示退出程序
修改后的代码

//client.go
package main

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

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8888")
	if err != nil {
		fmt.Println("客户端失败 err=", err)
		return
	}
	//功能一,客户端发送单行数据,然后输出
	reader := bufio.NewReader(os.Stdin)
	for {
		//从终端读取一行用户输入并准备发送给服务器
		line, err := reader.ReadString('\n') //返回一个字符串
		if err != nil {
			fmt.Println("radString err=", err)
		}
		line = strings.Trim(line, " \r\n") //去掉换行符
		//如果输入exit则退出
		if line == "exit" {
			fmt.Println("客户端退出")
			break
		}
		//再将line 发送给服务器
		_, err = conn.Write([]byte(line + "\n")) //在上面去掉了换行,在下面补回来  可能存在丢包和网络阻塞
		if err != nil {
			fmt.Println("conn.Write err=", err)
		}
	}
}

Q.E.D.