前两天用 GO 写一个网站的爬虫练手,但爬下来的内容是乱码的,一看原来该网站是 GBK 编码的,而 GO 中默认编码是 UTF-8 的,所以会导致非 UTF-8 的内容是乱码的。

于是我去找了一下 GO 的转码库,主要有 mahonia、iconv-go、和官方的 golang.org/x/text 这三个库用的比较多。

对这三个库都使用了一下,发现都不是很满意。下面看一下这三个库的 GBK 转 UTF-8。

  • mahonia
package main

import "fmt"
import "github.com/axgle/mahonia"

func main() {
	testBytes := []byte{0xC4, 0xE3, 0xBA, 0xC3, 0xA3, 0xAC, 0xCA, 0xC0, 0xBD, 0xE7, 0xA3, 0xA1}
	testStr := string(testBytes)
	enc := mahonia.NewDecoder("gbk")
	res := enc.ConvertString(testStr)
	fmt.Println(res) // 你好,世界!
}
复制代码
  • iconv-go
package main

import (
	"fmt"

	"github.com/axgle/mahonia"
	iconv "github.com/djimenez/iconv-go"
)

func main() {
	testBytes := []byte{0xC4, 0xE3, 0xBA, 0xC3, 0xA3, 0xAC, 0xCA, 0xC0, 0xBD, 0xE7, 0xA3, 0xA1}
	var res []byte
	iconv.Convert(testBytes, res, "GBK", "UTF-8")
	fmt.Printf(string(res)) // 你好,世界!
}
复制代码
  • golang.org/x/text
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"

	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

func main() {
	testBytes := []byte{0xC4, 0xE3, 0xBA, 0xC3, 0xA3, 0xAC, 0xCA, 0xC0, 0xBD, 0xE7, 0xA3, 0xA1}
	decoder := simplifiedchinese.GBK.NewDecoder()
	reader := transform.NewReader(bytes.NewReader(testBytes), decoder)
	res, _ := ioutil.ReadAll(reader)
	fmt.Printf(string(res)) // 你好,世界!
}

复制代码

上面就是这三个库的基本使用,可以发现这三个库都有一些问题:

string[]byteio.Readerstring[]byteio.Reader

transcode

我思索了一下,感觉链式调用是一个不错的解决方案,于是造了一个轮子,叫做 transcode,下面看一下使用方式:

  • GBK 转 UTF-8
package main

import (
	"fmt"

	"github.com/piex/transcode"
)

func main() {
	testBytes := []byte{0xC4, 0xE3, 0xBA, 0xC3, 0xA3, 0xAC, 0xCA, 0xC0, 0xBD, 0xE7, 0xA3, 0xA1}
	res := transcode.FromByteArray(testBytes).Decode("GBK").ToString()
	fmt.Printf(res) // 你好,世界
}
复制代码
  • UTF-8 转 GBK
package main

import (
	"bytes"
	"fmt"

	"github.com/piex/transcode"
)

func main() {
	testBytes := []byte{0xC4, 0xE3, 0xBA, 0xC3, 0xA3, 0xAC, 0xCA, 0xC0, 0xBD, 0xE7, 0xA3, 0xA1}
	testStr := "你好,世界!"
	res := transcode.FromString(testStr).Encode("GBK").ToByteArray()
	fmt.Println(bytes.Equal(res, testBytes)) // true
}
复制代码
string[]byte
ToStringToByteArray
io.Reader