golang常見字符串拼接通用處理方式

我們在日常開發中,尤其是對接第三方登錄、支付、分享等功能時,
時常需要對自己或接收到的數據進行一定的排序拼接後,
然後進行或加密或校驗的處理,雖然寫死順序可以解決問題,但代碼缺少了靈活性。
本文從通用性角度,以golang語言來處理一般情況下的字符串拼接問題。

目前經常遇到的排序方式主要有以下兩種:

1、參數名ASCII碼從小到大排序

以下是微信開發者平臺的簽名要求:

簽名生成的通用步驟如下:
第一步,設所有發送或者接收到的數據爲集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特別注意以下重要規則:
◆ 參數名ASCII碼從小到大排序(字典序);
◆ 如果參數的值爲空不參與簽名;
◆ 參數名區分大小寫;
◆ 驗證調用返回或微信主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值作校驗。
◆ 微信接口可能增加字段,驗證簽名時必須支持增加的擴展字段
//JoinStringsInASCII 按照規則,參數名ASCII碼從小到大排序後拼接
//data 待拼接的數據
//sep 連接符
//onlyValues 是否只包含參數值,true則不包含參數名,否則參數名和參數值均有
//includeEmpty 是否包含空值,true則包含空值,否則不包含,注意此參數不影響參數名的存在
//exceptKeys 被排除的參數名,不參與排序及拼接
func JoinStringsInASCII(data map[string]string, sep string, onlyValues, includeEmpty bool, exceptKeys ...string) string {
	var list []string
	var keyList []string
	m := make(map[string]int)
	if len(exceptKeys) > 0 {
		for _, except := range exceptKeys {
			m[except] = 1
		}
	}
	for k := range data {
		if _, ok := m[k]; ok {
			continue
		}
		value := data[k]
		if !includeEmpty && value == "" {
			continue
		}
		if onlyValues {
			keyList = append(keyList, k)
		} else {
			list = append(list, fmt.Sprintf("%s=%s", k, value))
		}
	}
	if onlyValues {
		sort.Strings(keyList)
		for _,v := range keyList {
			list = append(list,data[v])
		}
	}else {
		sort.Strings(list)
	}
	return strings.Join(list, sep)
}

示例:

	data := make(map[string]string)
	data["appid"] = "wx_1234535"
	data["body"] = "test data"
	data["mch_id"] = "572836589"
	data["notify_url"] = "http://www.baidu.com"
	data["trade_type"] = "MWEB"
	data["spbill_create_ip"] = "192.169.0.1"
	data["total_fee"] = "100"
	data["out_trade_no"] = "2745890486870"
	data["nonce_str"] = "kdjskgjokghdk"
	data["sign"] = "signData"
	log.Println("str :", JoinStringsInASCII(data, "&", false, false, "sign"))
	log.Println("str2 :", JoinStringsInASCII(data, "&", true, false, "sign"))

示例結果:

str : appid=wx_1234535&body=test data&mch_id=572836589&nonce_str=kdjskgjokghdk&notify_url=http://www.baidu.com&out_trade_no=2745890486870&spbill_create_ip=192.169.0.1&total_fee=100&trade_type=MWEB
str2 : wx_1234535&test data&572836589&kdjskgjokghdk&http://www.baidu.com&2745890486870&192.169.0.1&100&MWEB

2.按照特定的參數順序拼接

//JoinStringsInOrder 數名按固定順序排列後拼接
//data 待拼接的數據
//sep 連接符
//onlyValues 是否只包含參數值,true則不包含參數名,否則參數名和參數值均有
//orders 按照順序的參數名,沒有的不參與拼接
func JoinStringsInOrder(data map[string]string, sep string,onlyValues bool, orders ...string) string {
	var list []string
	for _, key := range orders {
		if _,ok := data[key];!ok {
			continue
		}
		if onlyValues {
			list = append(list, data[key])
		}else {
			list = append(list, fmt.Sprintf("%s=%s", key, data[key]))
		}
	}
	return strings.Join(list, sep)
}

示例:

log.Println("str3 :", JoinStringsInOrder(data, "&", false, "appid","body","mch_id","notify_url"))
log.Println("str4 :", JoinStringsInOrder(data, "&", true, "appid","body","mch_id","notify_url"))

示例結果:

str3 : appid=wx_1234535&body=test data&mch_id=572836589&notify_url=http://www.baidu.com
str4 : wx_1234535&test data&572836589&http://www.baidu.com
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章