Go言語で文字コード変換


# 概要

Go言語では、文字コードは基本UTF-8が扱われているので、
他の文字コードを使用したい場合は変換する必要がある。

# 使用するモジュール

文字コード変換処理を行うために、以下のモジュールを利用した。

- code.google.com/p/go.text/encoding/japanese
- code.google.com/p/go.text/transform
- io/ioutil
- strings

前者2つはインストールする必要がある。


```bash:shell
go get code.google.com/p/go.text/encoding
go get code.google.com/p/go.text/encoding/japanese
```


# UTF-8 から Shift_JIS への変換

`UTF-8`から`Shift_JIS`に変換するコードは、以下のようになった。

```go:encode.go
package main

import (
        "code.google.com/p/go.text/encoding/japanese"
        "code.google.com/p/go.text/transform"
        "fmt"
        "io/ioutil"
        "strings"
)

// UTF-8 から ShiftJIS
func utf8_to_sjis(str string) (string, error) {
        iostr := strings.NewReader(str)
        rio := transform.NewReader(iostr, japanese.ShiftJIS.NewEncoder())
        ret, err := ioutil.ReadAll(rio)
        if err != nil {
                return "", err
        }
        return string(ret), err
}

func main() {
        str := "テスト"
        msg, err := utf8_to_sjis(str)
        if err != nil {
                panic(err)
        }
        fmt.Println(msg)
}
```

# 変換処理概要

`tranform.NewReader`に渡すため、`string`型から`io.Reader`型に変換する。

```go:encode.go
iostr := strings.NewReader(str)
```

この変換したものを`transform.NewReader`の第一引数に渡し、
第二引数で変換文字コードを渡している。

第二引数で渡すもの。
http://godoc.org/code.google.com/p/go.text/encoding/japanese

```go:encode.go
rio := transform.NewReader(iostr, japanese.ShiftJIS.NewEncoder())
```

変換した結果が`io.Reader`型で帰ってくるので、`ioutil.ReadAll`で読み込んでいる。

```go:encode.go
ret, err := ioutil.ReadAll(rio)
```

変換が成功した場合は、結果を`string`型にキャストする。

```go:encode.go
return string(ret), err
```


# その他の変換

`UTF-8`と`Shift_JIS`、`UTF-8`と`EUC-JP`のそれぞれで相互変換する処理を書いたので載せておく。

```go:encode.go
package main

import (
        "code.google.com/p/go.text/encoding/japanese"
        "code.google.com/p/go.text/transform"
        "fmt"
        "io/ioutil"
        "strings"
)

// UTF-8 から ShiftJIS
func utf8_to_sjis(str string) (string, error) {
        ret, err := ioutil.ReadAll(transform.NewReader(strings.NewReader(str), japanese.ShiftJIS.NewEncoder()))
        if err != nil {
                return "", err
        }
        return string(ret), err
}


// ShiftJIS から UTF-8
func sjis_to_utf8(str string) (string, error) {
        ret, err := ioutil.ReadAll(transform.NewReader(strings.NewReader(str), japanese.ShiftJIS.NewDecoder()))
        if err != nil {
                return "", err
        }
        return string(ret), err
}

// UTF-8 から EUC-JP
func utf8_to_eucjp(str string) (string, error) {
        ret, err := ioutil.ReadAll(transform.NewReader(strings.NewReader(str), japanese.EUCJP.NewEncoder()))
        if err != nil {
                return "", err
        }
        return string(ret), err
}

// EUC-JP から UTF-8
func eucjp_to_utf8(str string) (string, error) {
        ret, err := ioutil.ReadAll(transform.NewReader(strings.NewReader(str), japanese.EUCJP.NewDecoder()))
        if err != nil {
                return "", err
        }
        return string(ret), err
}

func main() {
        str := "テスト"
        msg, err := utf8_to_sjis(str)
        if err != nil {
                panic(err)
        }
        msg, err = sjis_to_utf8(msg)
        fmt.Println(msg)
}
```


# 参考

package encoding
http://godoc.org/code.google.com/p/go.text/encoding

stringからio.Readerへの変換したい
http://qiita.com/abe00makoto/items/e01f817f3d83d60a378d

golangでIRCボットを書くときのメモ
http://www.binzume.net/diary/2014-07-08:A1