提示:本系列文章适合有其他语音基础并对Go有持续冲动的读者

一、golang获取HTTP请求

1.在golang标准库中提供了net包来处理网络连接,通过http.Get创建http请求并返回服务器响应流。再通过ReadAll读取response全部内容。
package main

import (
"fmt"
"io/ioutil"
"net/http"
"os"
) func main() {
for _, arg := range os.Args[1:] {
res, err := http.Get(arg)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
b, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("%s", b)
}
}

以访问360为例

超时会当成错误被捕获


二、练习

1.函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中,使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout,避免申请一个缓冲区(例子中的b)来存储。记得处理io.Copy返回结果中的错误。

package main

import (
"bufio"
"fmt"
"io"
"net/http"
"os"
) func main() {
for _, arg := range os.Args[1:] {
res, err := http.Get(arg)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
out, err := os.Create("/tmp/buf_file2.txt")
// 初始化一个 io.Writer
wt := bufio.NewWriter(out)
result, err := io.Copy(wt, res.Body)
defer res.Body.Close() if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(result)
wt.Flush()
}
}

2.如果输入的url参数没有 http:// 前缀的话,为这个url加上该前缀。你可能会用到strings.HasPrefix这个函数。

strings.Hasprefix(s, prefix)可以识别字符串的开头,如s字符串以prefix开头则返回true,否则为false,函数原型如下:

func HasPrefix(s, prefix string) bool {
return len(s) >= len(prefix) && s[0:len(prefix)] == prefix //通过切片处理
}

我们只需对参数做判断即可。

package main

import (
"bufio"
"fmt"
"io"
"net/http"
"os"
"strings"
) func main() {
for _, arg := range os.Args[1:] {
if strings.HasPrefix(arg, "http://") {
fmt.Println(arg)
get_txt(arg)
} else {
arg = "http://" + arg
get_txt(arg)
fmt.Println(arg)
}
}
} func get_txt(arg string) {
res, err := http.Get(arg)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
out, err := os.Create("/tmp/buf_file2.txt")
// 初始化一个 io.Writer
wt := bufio.NewWriter(out)
result, err := io.Copy(wt, res.Body)
defer res.Body.Close() if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(result)
wt.Flush()
}

3.h打印出HTTP协议的状态码,可以从resp.Status变量得到该状态码。

我们增加一个get_code函数如下,在main将get_txt替换为get_code即可:

func get_code(arg string) {
res, err := http.Get(arg)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
status := res.Status
fmt.Println("Http Code :", status)
}

结果如下:


三、初尝golang并发(扩展)

轻松创建高并发应用是go的特点之一,在我们请求多个url时也可以通过goroutime(我理解为协程)来创建并发,再通过信道来传递协程中的数据。我们来创建一个同时请求所有url的应用。

新创建一个new_routime(arg string, ch chan<- string goroutime,传入命令行参数、行道。该函数中包含start_timeend_time用于计算此协程运行的时间。

package main

import (
"bufio"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
) func get_txt(arg string) {
// ...
}
func get_code(arg string) {
// ...
}
func main() {
start := time.Now() //记录开始时间
ch := make(chan string) //创建一个字符信道 for _, arg := range os.Args[1:] {
//根据参数开启协程
if strings.HasPrefix(arg, "http://") {
go new_routime(arg, ch)
} else {
arg = "http://" + arg
go new_routime(arg, ch)
}
}
//读取信道数据
for range os.Args[1:] {
fmt.Println(<-ch)
}
end := time.Since(start).Seconds() //结束时间
fmt.Printf("time used :%.2fs\n", end)
}
func new_routime(arg string, ch chan<- string) {
start_time := time.Now()
res, err := http.Get(arg)
if err != nil {
ch <- fmt.Sprintf("err:", err)
return
}
size_bytes, err := io.Copy(ioutil.Discard, res.Body)
res.Body.Close()
if err != nil {
ch <- fmt.Sprintf("reading usl:%v", err)
return
}
end_time := time.Since(start_time).Seconds()
ch <- fmt.Sprintf("%.2fs %10d %s", end_time, size_bytes, arg) //执行时间、请求大小、url
}

Sprintf将数据输出到字符串或信道对象中。

ioutil.Discard是一个临时垃圾回收站,可以将不关注数据输出到此。

执行后结果如下:


书籍参考:Go语言圣经

文章有不足的地方欢迎在评论区指出。

欢迎收藏、点赞、提问。关注顶级饮水机管理员,除了管烧热水,有时还做点别的。

golang快速入门(四)的更多相关文章

  1. Golang快速入门

    Go语言简介: Golang 简称 Go,是一个开源的编程语言,Go是从2007年末由 Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian L ...

  2. AndroidStudio快速入门四:打造你的开发工具,settings必备

    http://blog.csdn.net/jf_1994/article/details/50085825 前言:这里是使用AS的基本设置,适合新入手的朋友阅读,将这里介绍的设置完基本使用无忧啦. 1 ...

  3. golang快速入门(六)特有程序结构

    提示:本系列文章适合对Go有持续冲动的读者 阅前须知:在程序结构这章,更多会关注golang中特有结构,与其他语言如C.python中相似结构(命名.声明.赋值.作用域等)不再赘述. 一.golang ...

  4. Golang快速入门:从菜鸟变大佬

    最近写了不少Go代码,但是写着写着,还是容易忘,尤其是再写点Python代码后.所以找了一篇不错的Golang基础教程,翻译一下,时常看看. 原文链接: 「Learning Go - from zer ...

  5. golang快速入门(五)初尝web服务

    提示:本系列文章适合对Go有持续冲动的读者 初探golang web服务 golang web开发是其一项重要且有竞争力的应用,本小结来看看再golang中怎么创建一个简单的web服务. 在不适用we ...

  6. Ant快速入门(四)-----Ant的任务(Task)

    到目前为止,我们已经掌握了Ant生成文件的基本结构,以及<project.../>,<target.../>,<property.../>等元素的配置方式.而< ...

  7. mybatis快速入门(四)

    mybatis动态标签<where><if><foreach>以及sql片段 1.创建一个包装类UserQueryVo.java package cn.my.myb ...

  8. Solr.NET快速入门(四)【相似查询,拼写检查】

    相似查询 此功能会返回原始查询结果中返回的每个文档的类似文档列表. 参数通过QueryOptions的MoreLikeThis属性定义. 示例:搜索"apache",为结果中的每个 ...

  9. golang快速入门(练习)

    1.打包和工具链 1.1 包 所有 Go 语言的程序都会组织成若干组文件,每组文件被称为一个包. ? 1 2 3 4 5 6 7 8 9 10 net/http/     cgi/     cooki ...

随机推荐

  1. shell脚本 4 函数与正则

    shell函数 shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数.给这段代码起个名字称为函数名,后续可以直接调用该段代码. 格式 func() {   #指定函数名 ...

  2. Deployment常用命令

    // 查询详细信息,获取升级速度 kubectl describe deployments // 暂停升级 kubectl rollout pause deployment/deploymentngi ...

  3. Day14_85_通过反射机制修改Class的属性值(IO+Properties)动态修改

    通过反射机制修改Class的属性值(IO+Properties)动态修改 import java.io.FileInputStream; import java.io.FileNotFoundExce ...

  4. Dynamics CRM实体系列之键

    这一节开始讲一下Dynamics CRM实体的键.键的作用个我们平时创建Primary Key的概念差不多.保证数据的唯一性. 键的设置在后台实体导航下面的键选项 点击新建创建一个键,会弹出一个窗口进 ...

  5. 03 Django web服务开发 - URL路由

    Django中的APP -Django中的一个APP就是一个应用的意思 -项目可以包含多个APP(多个应用) -一个项目对应一个网站(生活服务网站) 一个APP队形网站的一个应用(二手交易,家政服务) ...

  6. hdu4846 最大子正方形(dp)

    题意:       给你一个图,让你找到最大的子矩形. 思路:       之前做过一个最大子矩阵,记得当时是用三种方法做的,两种都是瓶颈法,第三种是dp,结果今天的用瓶颈吧怎么都过不去,哎!不知道为 ...

  7. POJ 1961 KMP(当前重复次数)

    题意:       前缀重复次数,举个例子,aaa 2的位置2个a,3的位置3个a abcabcabc 6的位置两个abcabc,9的位置三个abcabc.... 思路:      KMP基础题目之一 ...

  8. UVA11419 我是SAM

    题意:      给你一个n*m的矩阵,上面有一些格子上有目标,我们可以在格子的外面用枪打目标,一发子弹可以消灭一行或者一列目标,问你最少多少枪能把目标打光,并且输出开枪的位置,题目没说spj(特判) ...

  9. Andrew Ng机器学习算法入门(十):过拟合问题解决方法

    在使用机器学习对训练数据进行学习和分类的时候,会出现欠拟合和过拟合的问题.那么什么是欠拟合和过拟合问题呢?

  10. C++ 三消游戏基本实现

    最近在研究三消算法,我想试试在完全不借助网络资源的情况下搞定这个东西,所以有些地方可能不是最优的. 代码留此备忘. 1. 3x_desk_event.h 1 #pragma once 2 3 #ifn ...