[日常]go语言圣经--示例:并发的echo服务

陶士涵的菜地 陶士涵的菜地     2022-11-06     415

关键词:

最简单的回声服务器:

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语言圣经-示例:并发的目录遍历习题

练习8.9:编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来。packagemainimport(//"filepath""flag""fmt""io/ioutil""os""path""sync""time")/*练习8.9:编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来。*///接... 查看详情

[日常]go语言圣经-基于select的多路复用习题

练习8.8: 使用select来改造8.3节中的echo服务器,为其增加超时,这样服务器可以在客户端10秒中没有任何喊话时自动断开连接。reverb3.gopackagemainimport("bufio""fmt""log""net""strings""sync""time")funcmain()listener,err:=net.Listen("tcp",":8040")iferr 查看详情

[日常]go语言圣经--channel习题

练习8.3:在netcat3例子中,conn虽然是一个interface类型的值,但是其底层真实类型是*net.TCPConn,代表一个TCP连接。一个TCP连接有读和写两个部分,可以使用CloseRead和CloseWrite方法分别关闭它们。修改netcat3的主goroutine代码,只关闭网... 查看详情

[日常]go语言圣经--接口约定习题

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

[日常]go语言圣经-goroutines和线程

Goroutines和线程:1.动态栈: 1)线程都有一个固定大小的内存块(一般会是2MB)来做栈 2)一个goroutine会以一个很小的栈开始其生命周期,一般只需要2KB,不是固定的;栈的大小会根据需要动态地伸缩2.Goroutine调度: 1)线程是使用硬件定时器... 查看详情

[日常]go语言圣经--复数,布尔值,字符串习题

go语言圣经-复数1.我们把形如a+bi(a,b均为实数)的数称为复数,其中a称为实部,b称为虚部,i称为虚数单位。两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度2.complex函数用于构建复数,real和imag函数... 查看详情

[日常]go语言圣经-匿名函数习题2

练习5.13:修改crawl,使其能保存发现的页面,必要时,可以创建目录来保存这些页面。只保存来自原始域名下的页面。假设初始页面在golang.org下,就不要保存vimeo.com下的页面。packagemainimport("fmt""io""io/ioutil""links""log""net/http""net/url... 查看详情

[日常]go语言圣经--接口约定习题2

练习7.3: 为在gopl.io/ch4/treesort(§4.4)的*tree类型实现一个String方法去展示tree类型的值序列。packagemainimport("fmt""bytes")funcmain()//定义数组arr:=[...]int6,2,1,3,4,5vart*treefori:=0;i<len(arr);i++t=add(t,arr[i])/ 查看详情

[日常]go语言圣经--作用域,基础数据类型,整型

go语言圣经-作用域1.一个声明语句将程序中的实体和一个名字关联,比如一个函数或一个变量2.一个变量的生命周期是指程序运行时变量存在的有效时间段;声明语句的作用域对应的是一个源代码的文本区域,它是一个编译时的属性... 查看详情

[日常]go语言圣经-指针对象的方法-bit数组习题2

练习6.3: (*IntSet).UnionWith会用|操作符计算两个集合的交集,我们再为IntSet实现另外的几个函数IntersectWith(交集:元素在A集合B集合均出现),DifferenceWith(差集:元素出现在A集合,未出现在B集合),SymmetricDifference(并差集:元素出现... 查看详情

go语言并发编程

...的声音原样返回的过程。也就是回音(Echo)。本节使用Go语言中的s 查看详情

go语言圣经

今天将传说中的《Go语言圣经》,也就是《TheGoProgrammingLanguage》的中文版读完了。这本书鞭辟入里,读后醍醐灌顶。很大程度上提升了自己对Go代码编写的思维。尤其是在写过一段时间Go代码后,很多疑问顿时消解,甚是畅快淋漓... 查看详情

go语言之并发示例-pool

针对这个资源池管理的一步步都实现了,而且做了详细的讲解,下面就看下整个示例代码,方便理解。package commonimport (    "errors"    "io"    "sync"    "log")//一 查看详情

go语言之并发示例-pool

这篇文章演示使用有缓冲的通道实现一个资源池,这个资源池可以管理在任意多个goroutine之间共享的资源,比如网络连接、数据库连接等,我们在数据库操作的时候,比较常见的就是数据连接池,也可以基于我们实现的资源池来... 查看详情

go语言之并发示例(runner)

这篇通过一个例子,演示使用通道来监控程序的执行时间,生命周期,甚至终止程序等。我们这个程序叫runner,我们可以称之为执行者,它可以在后台执行任何任务,而且我们还可以控制这个执行者,比如强制终止它等。现在开... 查看详情

go语言圣经-panic异常,recover捕获异常习题

Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer机制)2.不是所有的panic异常都来自运行时,直接调用内置的panic函数也会引发panic异常;panic函数接受任何值作为参数。3.由... 查看详情

go语言的应用

Go语言由Google公司开发,并于2009年开源,相比Java/Python/C等语言,Go尤其擅长并发编程,性能堪比C语言,开发效率肩比Python,被誉为“21世纪的C语言”。Go语言在云计算、大数据、微服务、高并发领域应用应用非常广泛。BAT大厂正... 查看详情

7.3go语言中通过waitgroup控制并发(代码片段)

...发,但是在开发习惯上与显示的表达不太相同,所以在Go语言中可以利用sync包中的WaitGroup实现并发控制,更加直观。基本使用示例我们将之前的示例加以改造,引入sync.WaitGroup来实现并发控制。首先我们在主函数中定义WaitGroupvarw... 查看详情