Go语言Tips

Go语言Tips

2017-12-13 作者: 张子阳 分类: Go 语言

转型到Go以后,因为语言的不熟悉,以往很常见的一些操作有时候也需要去Google一下。这里将一些结果记录下来,方便日后查阅。

这篇文章没有什么讲解,都是一些小例子,有点类似于:go by example

如何解析XML?

我没有找到类似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按照key进行排序?

无法对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])
    }
}

如何生成Md5加密字符串?

// 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) 
}

如何获取当前的GOPATH路径?

func main(){
    fmt.Println(build.Default.GOPATH)
}

如何发起HttpGet请求,并以字符串返回结果?

// 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请求,并以字符串返回结果?

// 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
}

如何生成QR二维码

首先 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获取当前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
}

感谢阅读,希望这篇文章能给你带来帮助!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏软件开发

前端MVC Vue2学习总结(三)——模板语法、过滤器、计算属性、观察者、Class 与 Style 绑定

Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,...

62510
来自专栏C/C++基础

web前端开发初学者十问集锦(1)

答:script标签可以放置在html文件的任何地方(any where),比如既可以放置在html标签外,也可以放置在head内,也可以放置在body内,也可...

831
来自专栏Golang语言社区

golang(Go语言) byte/[]byte 与 二进制形式字符串 互转

效果 把某个字节或字节数组转换成字符串01的形式,一个字节用8个”0”或”1”字符表示。比如: byte(3) –> “00000011” []byte{1...

4777
来自专栏更流畅、简洁的软件开发方式

基类、接口的应用——表单控件:一次添加、修改一条记录,一次修改多条记录。(上)

好久没发帖子了,又加了不少的功能呀。(图片仅是测试,不代表什么表情。) 本来我也想写一个2007的总结的,但是看到很多人都写了,我就不凑热闹了,写点和代码有关...

1945
来自专栏Java3y

Juqery就是这么简单

什么是Jquery? Jquey就是一款跨主流浏览器的JavaScript库,简化JavaScript对HTML操作 就是封装了JavaScript,能够简化我...

3375
来自专栏C/C++基础

web前端开发初学者十问集锦(5)

(1)立即执行函数的定义 立即执行函数(Immediately Invoked Function)是在页面加载时立即被执行的函数。

922
来自专栏前端儿

前端代码相关规范

项目目录和文件的命名使用小写字母,避免使用大写或驼峰,多个单词以下划线 _ 分隔  如:my_project/cast_detail.js

3603
来自专栏飞雪无情的博客

Go语言实战笔记(二十六)| Go unsafe 包之内存布局

unsafe,顾名思义,是不安全的,Go定义这个包名也是这个意思,让我们尽可能的不要使用它,如果你使用它,看到了这个名字,也会想到尽可能的不要使用它,或者更小心...

742
来自专栏IMWeb前端团队

React高阶组件(译)

本文作者:IMWeb zzbozheng 原文出处:IMWeb社区 未经同意,禁止转载 原文:https://daveceddia.com/extra...

1956
来自专栏纯洁的微笑

springboot(四):thymeleaf使用详解

在上篇文章springboot(二):web综合开发中简单介绍了一下thymeleaf,这篇文章将更加全面详细的介绍thymeleaf的使用。thymeleaf...

77010

扫码关注云+社区

领取腾讯云代金券