2017-12-13 作者: 张子阳 分类: Go 语言
转型到Go以后,因为语言的不熟悉,以往很常见的一些操作有时候也需要去Google一下。这里将一些结果记录下来,方便日后查阅。
这篇文章没有什么讲解,都是一些小例子,有点类似于:go by example
我没有找到类似C#中的xml API可以动态地解析xml结构, 或者通过XPath来对xml结构进行搜索。只能一次性映射成一个struct,然后通过struct的属性去访问,这样每次解析都要构建一个对应的struct,稍显麻烦,可能有更好的解决方案,只是我不知道吧。
好处是,即使xml和struct并不完全对应,也可以正确解析,否则就会变得无比麻烦。
// Root 根节点
type Root struct {
XMLName xml.Name `xml:"xml"`
ReturnCode string `xml:"return_code"`
ReturnMsg string `xml:"return_msg"`
ResultCode string `xml:"result_code"`
ErrCode string `xml:"err_code"`
ErrCodeDes string `xml:"err_code_des"`
CodeURL string `xml:"code_url"`
}
func testXML() {
xmlStr := `<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
<openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
<trade_type><![CDATA[Native]]></trade_type>
<code_url><![CDATA[weixin://wxpay/s/An4baqw]]></code_url>
</xml>`
xmlByte := []byte(xmlStr)
var root Root
xml.Unmarshal(xmlByte, &root)
fmt.Println(root.ReturnCode)
fmt.Println(root.CodeURL)
fmt.Println("root.ErrCode", root.ErrCode) // 这个是没有的
}
Go的字符串类型转换有时候真的是让萌新有点犯晕。
func convertToString() {
var text string
// int 转换成字符串
text = strconv.Itoa(10000)
fmt.Println("text:", text)
// interface{} 转换成字符串
var i interface{}
i = "hello"
text = i.(string)
fmt.Println("text:", text)
// byte[] 转换成字符串
data := []byte("world")
text = string(data)
fmt.Println("text:", text)
}
这个小小的以日期+随机数作为唯一编号的函数包含了这两个功能。
func GetDateNo() string {
// 生成随机数:0~9999
src := rand.NewSource(time.Now().UnixNano())
r := rand.New(src)
suffix := strconv.Itoa(r.Intn(10000))
// 最大长度为4,并且用0来补齐
if len(suffix) < 4 {
suffix = fmt.Sprintf("%04s", suffix)
}
str := time.Now().Format("060102150405") + suffix
return str
}
无法对map进行排序,如果需要按顺序处理map,可以用下面的方法间接进行。
// 对map进行排序
func sortMap(dic map[string]string) {
var keys []string
for k := range dic {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
// 在这里进行处理
fmt.Println(k, ":", dic[k])
}
}
// GetMd5 获得md5字符串
func GetMd5(text string) string {
data := []byte(text)
cryptoData := md5.Sum(data)
cryptoText := hex.EncodeToString(cryptoData[:])
return cryptoText
}
func main() {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
}
fmt.Println("Path:", dir)
}
func main(){
fmt.Println(build.Default.GOPATH)
}
// HTTPGet 发起HttpGet请求,并返回string格式的结果
func HTTPGet(url string) (string, error) {
res, err := http.Get(url)
if err != nil {
log.Error(err.Error(), "HTTPGet")
return "", err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Error(err.Error(), "HTTPGet")
return "", err
}
return string(body), nil
}
// HTTPPost 发起http post请求
func HTTPPost(url string, body string) (string, error) {
data := []byte(body)
reader := bytes.NewReader(data)
res, err := http.Post(url, "application/x-www-form-urlencoded", reader)
if err != nil {
log.Error(err.Error(), "HTTPPost-1")
return "", err
}
resBody, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Error(err.Error(), "HTTPPost-2")
return "", err
}
return string(resBody), nil
}
首先 go get github.com/boombuler/barcode
,然后看下面范例。
package main
import (
"bytes"
"fmt"
"image/png"
"os"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
)
生成QR图片
func createQRImage() {
qrCode, _ := qr.Encode("http://www.baidu.com", qr.M, qr.Auto)
qrCode, _ = barcode.Scale(qrCode, 200, 200)
file, _ := os.Create("qrcode.png")
defer file.Close()
png.Encode(file, qrCode)
}
生成QR byte数组(应该更常用一些,可以直接http返回)
func createQRByte() []byte {
qrCode, _ := qr.Encode("http://www.baidu.com", qr.M, qr.Auto)
qrCode, _ = barcode.Scale(qrCode, 200, 200)
buf := new(bytes.Buffer)
png.Encode(buf, qrCode)
bytes := buf.Bytes()
return bytes
}
因为我们的时区是UTC+8,所以关于时间,如果不小心处理就会出现相差8小时的错误。看下面的代码:
func main() {
const LayOut = "2006-01-02 15:04:05"
// 获取当前日期并转换为字符串打印
now := time.Now()
nowStr := now.Format(LayOut)
fmt.Println(nowStr)
// 将字符串转换为日期,再转换回去然后打印
now2, _ := time.Parse(LayOut, nowStr)
now2Str := now2.Format(LayOut)
fmt.Println(now2Str)
diff := now.Sub(now2)
fmt.Println("total :", diff.Hours())
}
按正常理解,这样转换后的结果应该是完全一致的,结果实际上now比now2早了8小时。
2017-12-14 14:53:00
2017-12-14 14:53:00
total : -7.999736999166666
字符串的值完全相等,但是diff一下发现实际不一样。其实将上面的例子稍微修改一下,就知道差别了:
// 相同代码省略
fmt.Println(now.String())
fmt.Println(now2.String())
输出为:
2017-12-14 15:05:12.3921453 +0800 CST
2017-12-14 15:05:12 +0000 UTC
total : -7.99989107075
可以看到两个时间是不一样的,所以在从字符串转换为日期的时候,需要将当前时区传进去,这里是正确版本:
Beijing, _ := time.LoadLocation("Asia/Shanghai")
now2, _ := time.ParseInLocation(LayOut, nowStr, Beijing)
fmt.Println(now2.String())
本想通过url.URL获取当前URL全路径,结果本地(localhost)测试时,scheme为空,host为空,所以通过http.Request来获得,结果scheme还是空。没有啥其他办法,暂时写死了。
func getFullURL(r *http.Request) string {
return "http://" + r.Host + r.RequestURI
// return r.URL.Scheme + "://" + r.Host + r.RequestURI
}
感谢阅读,希望这篇文章能给你带来帮助!