Go语言:编写一个 WebsiteRacer 的函数,用来对比请求两个 URL 来「比赛」,并返回先响应的 URL。如果两个 URL 在 10 秒内都未返回结果,返回一个 error。

寻技术 Go编程 2023年07月12日 59

问题:

你被要求编写一个叫做 WebsiteRacer 的函数,用来对比请求两个 URL 来「比赛」,并返回先响应的 URL。如果两个 URL 在 10 秒内都未返回结果,那么应该返回一个 error

 
实现这个功能我们需要用到
  •  net/http 用来调用 HTTP 请求
  •  net/http/httptest 用来测试这些请求
  •  Go 程(goroutines)
  •  select

 

先写测试

我们从最幼稚的做法开头把事情开展起来。
func TestRacer(t *testing.T) {
    slowURL := "http://www.facebook.com"
    fastURL := "http://www.quii.co.uk"

    want := fastURL
    got := Racer(slowURL, fastURL)

    if got != want {
        t.Errorf("got '%s', want '%s'", got, want)
    }
}

我们知道这样不完美并且有问题,但这样可以把事情开展起来。重要的是,不要徘徊在第一次就想把事情做到完美。

尝试运行测试

./racer_test.go:14:9: undefined: Racer

为测试的运行编写最少量的代码,并检查失败测试的输出

func Racer(a, b string) (winner string) {
    return
}

racer_test.go:25: got '', want 'http://www.quii.co.uk'

编写足够的代码使程序通过

func Racer(a, b string) (winner string) {
    startA := time.Now()
    http.Get(a)
    aDuration := time.Since(startA)

    startB := time.Now()
    http.Get(b)
    bDuration := time.Since(startB)

    if aDuration < bDuration {
        return a
    }

    return b
}
对每个 URL:
  • 1.我们用 time.Now() 来记录请求 URL 前的时间。
  • 2.然后用 http.Get 来请求 URL 的内容。这个函数返回一个 http.Response 和一个 error,但目前我们不关心它们的值。
  • 3.time.Since 获取开始时间并返回一个 time.Duration 时间差。

我们完成这些后就可以通过对比请求耗时来找出最快的了。

 

问题

 
这可能会让你的测试通过,也可能不会。问题是我们通过访问真实网站来测试我们的逻辑。
使用 HTTP 测试代码非常常见,Go 标准库有这类工具可以帮助测试。
 在前两章模拟和依赖注入章节中,我们讲到了理想情况下如何不依赖外部服务来进行测试,因为它们可能
  • 速度慢
  •  不可靠
  •  无法进行边界条件测试
在标准库中有一个 net/http/httptest 包,它可以让你轻易建立一个 HTTP 模拟服务器(mock HTTP server)。
我们改为使用模拟测试,这样我们就可以控制可靠的服务器来测试了。
func TestRacer(t *testing.T) {

    slowServer := httptest.NewServer(http.HandlerFunc(func(w        
         
      
关闭

用微信“扫一扫”