最简单的回声服务器:

package main

import (
"io"
"net"
"log"
) func main() {
listener, err := net.Listen("tcp", ":8040")
if err != nil {
log.Fatal(err)
} for {
conn, err := listener.Accept()
if err != nil {
log.Print(err) // e.g., connection aborted
continue
}
go handleConn(conn) //新建goroutines处理连接
}
} func handleConn(c net.Conn) {
io.Copy(c, c) // NOTE: ignoring errors
c.Close()
}

原理:

1.io.Copy()方法
func Copy(dst Writer, src Reader) (written int64, err error)

2.net.Conn类型
type Conn interface {
Read(b []byte) (n int, err error)
Write(b []byte) (n int, err error)
...
}
一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口

3.io.Writer
type Writer interface {
Write(p []byte) (n int, err error)
}
4.io.Reader
type Reader interface {
Read(p []byte) (n int, err error)
}

升级版,每条连接一个goroutine,每个goroutine中分出多个输出goroutine

package main

import (
"bufio"
"fmt"
"log"
"net"
"strings"
"time"
) func main() {
listener, err := net.Listen("tcp", ":8040")
if err != nil {
log.Fatal(err)
} for {
conn, err := listener.Accept()
if err != nil {
log.Print(err) // e.g., connection aborted
continue
}
go handleConn(conn) //新建goroutines处理连接
}
} func handleConn(c net.Conn) {
input := bufio.NewScanner(c)
for input.Scan() {
go echo(c, input.Text(), 1*time.Second)
}
// NOTE: ignoring potential errors from input.Err()
c.Close()
}
func echo(c net.Conn, shout string, delay time.Duration) {
fmt.Fprintln(c, "\t", strings.ToUpper(shout))
time.Sleep(delay)
fmt.Fprintln(c, "\t", shout)
time.Sleep(delay)
fmt.Fprintln(c, "\t", strings.ToLower(shout))
}

  

1.fmt.Fprintln()
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)

2.bufio.NewScanner()
func NewScanner(r io.Reader) *Scanner
func (s *Scanner) Scan() bool
func (s *Scanner) Text() string

也用到了大量的7.3节 实现接口的条件

  

[日常] Go语言圣经--示例: 并发的Echo服务的更多相关文章

  1. [日常] Go语言圣经--示例: 并发的Clock服务习题

    练习 8.1: 修改clock2来支持传入参数作为端口号,然后写一个clockwall的程序,这个程序可以同时与多个clock服务器通信,从多服务器中读取时间,并且在一个表格中一次显示所有服务传回的结 ...

  2. [日常] Go语言圣经-示例: 并发的目录遍历习题

    练习 8.9: 编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来. package main import ( // "filepath" "fla ...

  3. [日常] GO语言圣经-并发获取多个URL

    go语言圣经-并发获取多个URL 1.GO最新奇的特性就是对并发编程的支持,goroutine和channel 2.goroutine是一种函数的并发执行方式,而channel是用来在goroutin ...

  4. [日常] Go语言圣经-WEB服务与习题

    Go语言圣经-web服务 1.Web服务程序,标准库里的方法已经帮我们完成了大量工作 2.main函数将所有发送到/路径下的请求和handler函数关联起来,/开头的请求其实就是所有发送到当前站点上的 ...

  5. [日常] Go语言圣经前言

    https://books.studygolang.com/gopl-zh/ go语言圣经 1.Go语言有时候被描述为“C类似语言”,或者是“21世纪的C语言”. 2.Go语言中和并发编程相关的特性是 ...

  6. [日常] Go语言圣经--接口约定习题

    Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自 ...

  7. [日常] Go语言圣经-Panic异常,Recover捕获异常习题

    Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)2.不是所有的panic异常都来自运行时,直接调用内置的pan ...

  8. [日常] Go语言圣经-匿名函数习题

    Go语言圣经-匿名函数1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值2.通过这种方式定义的函数可以访 ...

  9. [日常] Go语言圣经-错误,函数值习题

    Go语言圣经-错误 1.panic异常.panic是来自被调函数的信号,表示发生了某个已知的bug 2.任何进行I/O操作的函数都会面临出现错误的可能 3.错误是软件包API和应用程序用户界面的一个重 ...

随机推荐

  1. ue4开发入门教程

    ue4是一套开源跨平台的游戏引擎,游戏画质3A水准,具有强大的材质编辑器,各种插件齐全.想要学习ue4的,可以参考这篇文章作为入门. 学习这篇文章,建议具有一定的C++基础,对游戏有一定了解. 1.首 ...

  2. 键'attachdbfilename'的值无效。

    ---恢复内容开始--- ---恢复内容结束---

  3. WPF ListBox的进阶使用(二)

    项目中经常使用需要根据搜索条件查询数据,然后用卡片来展示数据.用卡片展示数据时,界面的宽度发生变化,希望显示的卡片数量也跟随变化.WrapPanel虽然也可以实现这个功能,但是将多余的部分都留在行尾, ...

  4. 5. ASP.NET MVC 中的Areas【区域】是什么

    [PS返回上一篇:-->4.ASP.NET MVC 5.0 视图之模型绑定] 从ASP.NET MVC 2.0开始,微软就提供了一个新特性:Areas[区域].Areas仅仅是用来将大型程序拆分 ...

  5. Android 四大组件之" ContentProvider "

    前言 ContentProvider作为Android的四大组件之一,是属于需要掌握的基础知识,可能在我们的应用中,对于Activity和Service这两个组件用的很常见,了解的也很多,但是对Con ...

  6. Ubuntu18.04 - 安装深度桌面(Deepin Linux Desktop)

    深度Linux官网:https://www.deepin.org 深度桌面感觉确实不错,所以打算安装上来,以后体验一下,下面是安装的命令: 1, sudo add-apt-repository ppa ...

  7. CentOS修改yum源为阿里云

    yum的工具,自动去下载某个yum仓库的 rpm软件包,并且自动搜索软件下载软件依赖,如同pip3,npm等包管理工具 yum载linux中的 yum仓库是 /etc/yum.repos.d 并且在这 ...

  8. LOJ#3052. 「十二省联考 2019」春节十二响(启发式合并)

    题面 传送门 题解 先考虑一条链的情况,对于\(1\)号点来说,肯定是左子树中最大值和右子树中最大值一组,左子树中次大值和右子树中次大值一组--以此类推 那么如果不是一条链呢?我们把所有的链合并起来就 ...

  9. spring boot实现异步调用

    今天在这里学习下使用springboot的异步调用async 首先使用@EnableAsync开启异步功能 /** * @author fengzp * @date 17/5/8 * @email f ...

  10. @transactional注解,报错后数据库操作回滚失败

    1. https://jingyan.baidu.com/article/3a2f7c2e27d51b26afd611ff.html 2. https://blog.csdn.net/lee_star ...