leevis.com icon indicating copy to clipboard operation
leevis.com copied to clipboard

go 的 UrlEncode

Open vislee opened this issue 10 years ago • 0 comments

当我们在代码里面curl一个url的时候,有时候会遇到一些奇葩的设计,url里有中文需要对url进行编码。如果直接调用url.QueryEscape转码,http.Get()时候会报错"unsupported protocol scheme"。如果不转码那么又会报http status 400.

那么,该怎么转码呢?go里貌似也没有一个现成的函数供直接转url的参数的。那就需要我们自己封装一个:


func UrlEncode(u string) (string, error) {
    uary := strings.SplitAfterN(u, "?", 2)
    if len(uary) == 2 {
        m, e := url.ParseQuery(uary[1])
        if e != nil {
            return "", e
        }
        uary[1] = m.Encode()
    }
    return strings.Join(uary, ""), nil
}

补充16进制解码函数和2进制解码函数

package main

import (
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
)

func hexDecode(str string) string {
	s := strings.TrimPrefix(strings.TrimPrefix(str, "0x"), "0X")
	data, err := hex.DecodeString(s)
	if err != nil {
		return str
	}
	return string(data)
}

func binDecode(str string) string {
	var sb strings.Builder

	bt := []byte(strings.TrimPrefix(strings.TrimPrefix(str, "0b"), "0B"))
	l := len(bt)

	sb.Grow(l + 7)

	for b, e := 0, (l-1)%8+1; e <= l; e += 8 {
		c, err := strconv.ParseUint(string(bt[b:e]), 2, 32)
		if err != err {
			return str
		}
		sb.WriteString(string(c))
		b = e + 1
	}

	return sb.String()
}

func main() {
	fmt.Println(binDecode("0b01100001") == "a")
	fmt.Println(binDecode("0B01100001") == "a")
	fmt.Println(binDecode("01100001") == "a")
	fmt.Println(binDecode("0b1100001") == "a")
	fmt.Println(binDecode("0B1100001") == "a")
	fmt.Println(binDecode("1100001") == "a")

	fmt.Println(hexDecode(binDecode("0b001100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("0B001100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("001100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("0b01100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("0B01100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("01100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("0b1100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("0B1100100110011000110010001100000011011000110010")) == "/ b")
	fmt.Println(hexDecode(binDecode("1100100110011000110010001100000011011000110010")) == "/ b")
}

优化2进制解码函数

func binDecode(str string) string {
	var sb bytes.Buffer

	bt := []byte(strings.TrimPrefix(strings.TrimPrefix(str, "0b"), "0B"))
	l := len(bt)

	sb.Grow(l + 7)
	for b, e := 0, (l-1)%8+1; e <= l; e += 8 {
		c, err := strconv.ParseUint(string(bt[b:e]), 2, 32)
		if err != err {
			return str
		}
		sb.WriteByte(byte(c))
		b = e + 1
	}

	return sb.String()
}

vislee avatar Jan 04 '16 11:01 vislee