Upgrade to Pro — share decks privately, control downloads, hide ads and more …

UTF-8 依存の Go コードとは?

UTF-8 依存の Go コードとは?

BigLT 2019

8843d0fb02a3688513a890bd23a5fa3c?s=128

acomagu

June 29, 2019
Tweet

Transcript

  1. UTF-8依存のGoコードとは 190629 Aizu BigLT @acomagu

  2. 今日のゴール - Goの標準の文字コードとは何か? - UTF-8依存のコードとは? - 正しくUTF-8を処理する方法を知る → ドキュメントと実装に差異がないようにしよう

  3. Go標準の文字コードとは?

  4. s に入れるべき文字コードはわかりますか? (ここにある情報のみで)

  5. godoc.org/builtin

  6. godoc.org/builtin

  7. 特定の文字コードにしか対応しないなら ドキュメントに書かなければならない!

  8. None
  9. None
  10. でも... UTF-8依存のコードなんて 書いた覚えないけど?

  11. UTF-8依存のコードとは?

  12. UTF-8依存クイズ~!!

  13. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    }
  14. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return string(bts) } []byte -> string
  15. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return string(bts) } []byte -> string 非依存
  16. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return string(rns) } []rune -> string
  17. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return string(rns) } []rune -> string 依存
  18. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []byte(str) } string -> []byte
  19. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []byte(str) } string -> []byte 非依存
  20. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []byte(rns) } []rune -> []byte
  21. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []byte(rns) } []rune -> []byte 依存
  22. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []rune(str) } string -> []rune
  23. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []rune(str) } string -> []rune 依存
  24. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []rune(bts) } []byte -> []rune
  25. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return []rune(bts) } []byte -> []rune 依存
  26. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return len(str) }
  27. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    return len(str) } 非依存
  28. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    for i := 0; i < len(str); i++ { _ = str[i] } }
  29. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    for i := 0; i < len(str); i++ { _ = str[i] } } 非依存
  30. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    for i := range str { _ = str[i] } }
  31. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    for i := range str { _ = str[i] } } 依存
  32. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    bytes.Index([]byte(str1), []byte(str2)) }
  33. UTF-8依存? 非依存? func cast(str string, bts []byte, rns []rune) {

    bytes.Index([]byte(str1), []byte(str2)) } 依存
  34. お疲れ様です (ありがとうございます)

  35. まとめ - rune が絡むキャストはUTF-8依存 - string を range にかけるとUTF-8依存 -

    しかし len(str) や str[i] は非依存
  36. bytes.Index 問について... Shift-JISだと “表” “\” 0x95 0x5C 0x5C

  37. bytes.Index 問について... Shift-JISだと “表” “\” 0x95 0x5C 0x5C bytes.Index にかけるとまずい...

  38. bytes.Index 問について... 1バイト目 2バイト目以降

  39. bytes.Index 問について... 1バイト目 2バイト目以降 違う → bytes.Index大丈夫

  40. 正しくUTF-8を処理するには

  41. ① ASCII 依存にしない 例えば: UTF-8 で ”Number” はたくさんある → Unicode

    のキャラクタクラスを適切に利用する → コメントに ASCII Number のみと記載する
  42. ② 正規化/比較で正しい手順を踏む - 例えば: - Unicode の正規化と比較方法は RFC8264(PRECIS) として 定義されている

    - 「いつ使うべきか」も記述がある - golang.org/x/text/secure/precis
  43. ③ Grapheme Cluster を意識する Grapheme Cluster とは? → 「1文字の境界」を定義する仕様

  44. ③ Grapheme Cluster を意識する Grapheme Cluster とは? → 「1文字の境界」を定義する仕様 「1文字

    == 1コードポイント」じゃないの? → Variation Selector が付与されている場合がある
  45. ③ Grapheme Cluster を意識する 絵文字とか良くね?

  46. ③ Grapheme Cluster を意識する Go では大変... - 標準ライブラリにはない - 外部ライブラリを使用

    - Proposal は出てる - 正規表現での対応は不可能そう - \X ...
  47. まとめ - Go の型には UTF-8 依存のものはないが、キャストなどには いくつかある - ASCII 依存

    / PRECIS / Grepheme Cluster を意識する → どこまで対応しているのかドキュメントでしっかり明確にしよ う
  48. Thanks!