golang url encode
背景: net/url库没找到如何控制特殊字符不转码,自己实现
main:
package main import ( "ap/url_utils" "fmt" ) func main() { // :/?~%&+=;,@()!*#$' url := "http://www.baidu.com/aaa/:/?~%&+=;,@()!*#$''/bbb/sdf/斯蒂芬.dill" r := url_utils.QueryEscape(url) fmt.Println(r) }
utils:
package url_utils const upperhex = "0123456789ABCDEF" type encoding int const ( encodePath encoding = 1 + iota encodePathSegment encodeHost encodeZone encodeUserPassword encodeQueryComponent encodeFragment encodeURI ) // QueryEscape escapes the string so it can be safely placed // inside a URL query. func QueryEscape(s string) string { return escape(s, encodeURI) } func escape(s string, mode encoding) string { spaceCount, hexCount := 0, 0 for i := 0; i < len(s); i++ { c := s[i] if shouldEscape(c, mode) { if c == ' ' && mode == encodeQueryComponent { spaceCount++ } else { hexCount++ } } } if spaceCount == 0 && hexCount == 0 { return s } var buf [64]byte var t []byte required := len(s) + 2*hexCount if required <= len(buf) { t = buf[:required] } else { t = make([]byte, required) } if hexCount == 0 { copy(t, s) for i := 0; i < len(s); i++ { if s[i] == ' ' { t[i] = '+' } } return string(t) } j := 0 for i := 0; i < len(s); i++ { switch c := s[i]; { case c == ' ' && mode == encodeQueryComponent: t[j] = '+' j++ case shouldEscape(c, mode): t[j] = '%' t[j+1] = upperhex[c>>4] t[j+2] = upperhex[c&15] j += 3 default: t[j] = s[i] j++ } } return string(t) } // Return true if the specified character should be escaped when // appearing in a URL string, according to RFC 3986. // // Please be informed that for now shouldEscape does not check all // reserved characters correctly. See golang.org/issue/5684. func shouldEscape(c byte, mode encoding) bool { // §2.3 Unreserved characters (alphanum) if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' { return false } //:/?~%&+=;,@()!*#$' switch c { case '-', '_', '.', '~': return false case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', ':', '/', '?', '%', '@', '#': return false } // Everything else must be escaped. return true }