go语言带cookie的net客户端请求与[]byte转string

前些日子参加了一个叫Advent of Code的编程大赛,每天一道题,快活似神仙。这每道题都有自己的拼图数据输入puzzle input,要做题就需要用到该数据,把数据复制过来感觉又太麻烦,于是就兴起写了一个直接从html读取数据的函数。
数据如下:

+12
-10
-4
-8
+18
-1
-13
...

查看标准库文档,发现net/html包可以做这个功能,其函数如下:

resp, err := http.Get("http://example.com/")
if err != nil {
    // handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...

然后调试,但并未有相关数据输出,在浏览器中检查元素发现该请求需要带cookie才能正确返回数据。直接使用http.Get()并不带有cookie,所以改用NewRequest使用指定的方法、网址和可选的主题创建并返回一个新的*Request。其函数如下:

client := &http.Client{}
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Cookie", "name=value")
    resp, err := client.Do(req)

    robots, err := ioutil.ReadAll(resp.Body)


  resp.Body.Close()//必须要关闭Body

ioutil.ReadAll()返回的是[]byte类型,入需要使用可以先将[]byte转换成string,Go语言初学者都会的类型转换语法:string(b),Go为了稳定性对于上述方法需要经过一些数据上的复制,一旦数据量过大,这个成本是难以忍受的。
所以为了让Go服帖,我们得用上unsafe包,unsafe包提供一些可以跳过Go语言类型安全限制的操作。看下面代码:
go func BytesString(b []byte) string { return *(*string)(unsafe.Pointer(&b)) }
我们取到[]byte的指针,Go会说*byte不是*string,但是我们有外挂unsafe.Pointer,所以Go就通过了,接着你很自在的把*byte转成了*string,因为reflect.StringHeaderreflect.SliceHeader的结构体只相差末尾一个字段。
类似的用法可以看Go语言黑魔法
接着用regexp包正则表达式FindAllString取出匹配的[]string数据使用,然后再用strconv.Atoi()进行转化就可以了。
Day1的题为求和,其代码如下:

package main
import (
   "fmt"
   "io/ioutil"
   "log"
   "net/http"
   "os"
   "regexp"
   "strconv"
   "unsafe"
)
func BytesString(b []byte) string {//[]byte 转string
   return *(*string)(unsafe.Pointer(&b))
}
func getPuzzle(url string) string {//从网页抓取数据
   client := &http.Client{}
   req, err := http.NewRequest("GET", url, nil)
   if err != nil {
       log.Fatal(err)
   }
   req.Header.Set("Cookie", "session=53616c7xxx")
   resp, err := client.Do(req)
   robots, err := ioutil.ReadAll(resp.Body)
   resp.Body.Close()
   str := BytesString(robots)
   return str
}
func sum(num []int) int {
   sum := 0
   for _, n := range num {
       sum += n
   }
   return sum
}
func strtoint(str []string) []int {//string转int
   num := make([]int, len(str))
   for i := 0; i < len(str); i++ {
       flag := str[i][0]
       chafre, _ := strconv.Atoi(str[i][1:])
       switch flag {
       case '+':
           num[i] = chafre
       case '-':
           num[i] = -chafre
       }
   }
   return num
}
func main() {
   change := getPuzzle("https://adventofcode.com/2018/day/1/input")
   re := regexp.MustCompile("[+|-][0-9]*")//正则表达式
   str := re.FindAllString(change, -1)
   num := strtoint(str)
   sum := sum(num)
   fmt.Printf("sum is %d\n", sum)
}

如果有更好的方法,欢迎私信,哈哈哈···

转载于:https://www.cnblogs.com/ryan-mask/p/10067298.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值