golang 字符串编码转换 gbk转utf8

问题描述:
需要调取一个第三方的接口,接口返回的内容的编码格式是gbk的,但是golang内建只认utf8,所以需要将gbk的字符串转换为utf8,才能进行后续的数据处理。

问题处理:
引入开源包 go get github.com/axgle/mahonia
此包的开源协议是BSD,所以可以放心的引用和使用

mahonia源码解读:

// ConvertString converts a string from d's encoding to UTF-8.
func (d Decoder) ConvertString(s string) string {
    bytes := []byte(s)
    runes := make([]rune, len(s))
    destPos := 0

    for len(bytes) > 0 {
        c, size, status := d(bytes)

        if status == STATE_ONLY {
            bytes = bytes[size:]
            continue
        }

        if status == NO_ROOM {
            c = 0xfffd
            size = len(bytes)
            status = INVALID_CHAR
        }

        bytes = bytes[size:]
        runes[destPos] = c
        destPos++
    }

    return string(runes[:destPos])
}

      本以为调用上面这个函数就可以完成转换,结果发现返回的字符串的中文部分依旧是乱码。网上查阅资料后,发现还需要调用一个translate函数。

// Translate enables a Decoder to implement go-charset's Translator interface.
func (d Decoder) Translate(data []byte, eof bool) (n int, cdata []byte, err error) {
    cdata = make([]byte, len(data)+1)
    destPos := 0

    for n < len(data) {
        rune, size, status := d(data[n:])

        switch status {
        case STATE_ONLY:
            n += size
            continue

        case NO_ROOM:
            if !eof {
                return n, cdata[:destPos], nil
            }
            rune = 0xfffd
            n = len(data)

        default:
            n += size
        }

        if rune < 128 {
            if destPos >= len(cdata) {
                cdata = doubleLength(cdata)
            }
            cdata[destPos] = byte(rune)
            destPos++
        } else {
            if destPos+utf8.RuneLen(rune) > len(cdata) {
                cdata = doubleLength(cdata)
            }
            destPos += utf8.EncodeRune(cdata[destPos:], rune)
        }
    }

    return n, cdata[:destPos], nil
}

      内部的编码转换代码就不分析了,看了下没怎么看明白。。。就当一回拿来主义,看一下函数的入参和返回值,直接调用了。发现返回值有三个参数,n应该是字符串的容量或者长度,err我发现不管怎样都是返回nil,所以这两个参数对我来说我并不关心,只需要拿到第二个返回参数[]byte就行了。

      于是,封装成转换函数如下

//src为要转换的字符串,srcCode为待转换的编码格式,targetCode为要转换的编码格式
func ConvertToByte(src string, srcCode string, targetCode string) []byte {
    srcCoder := mahonia.NewDecoder(srcCode)
    srcResult := srcCoder.ConvertString(src)
    tagCoder := mahonia.NewDecoder(targetCode)
    _, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
    return cdata
}

      使用

response = util.ConvertToByte(string(response), "gbk", "utf8")
    err = json.Unmarshal(response, &result)
    if err != nil {
        logger.Error("error: ", err)
        return result, err
    }
    return result,nil

      大功告成

你可能感兴趣的:(golang)