简体   繁体   中英

ASCII encoding for string in GO

In Ruby, you can encode string to ASCII as follows:

str.force_encoding('ASCII')

How can we achieve the same in Go?

strconv.QuoteToASCII

QuoteToASCII returns a double-quoted Go string literal representing s. The returned string uses Go escape sequences (\\t, \\n, \\xFF, \Ā) for non-ASCII characters and non-printable characters as defined by IsPrint.

Or if you want an array of ascii codes, you could do

import "encoding/ascii85"
dst := make([]byte, 25, 25)
dst2 := make([]byte, 25, 25)
ascii85.Encode(dst, []byte("Hello, playground"))
fmt.Println(dst) 
ascii85.Decode(dst2, dst, false)
fmt.Println(string(dst2))

https://play.golang.org/p/gLEuWAGglJV

A simple version that omits invalid runes could look like this:

func forceASCII(s string) string {
  rs := make([]rune, 0, len(s))
  for _, r := range s {
    if r <= 127 {
      rs = append(rs, r)
    }
  }
  return string(rs)
}
// forceASCII("Hello, World!") // => "Hello, World!"
// forceASCII("Hello, 世界!") // => "Hello, !"
// forceASCII("Привет") // => ""

But what if you want special behavior if the target UTF-8 string contains any characters outside the ASCII character range of [0,127] ?

You could write a function that handles various cases by extracting a function argument which takes the invalid-ASCII rune and returns a string replacement or error.

For example ( Go Playground ):

func forceASCII(s string, replacer func(rune) (string, error)) (string, error) {
  rs := make([]rune, 0, len(s))
  for _, r := range s {
    if r <= 127 {
      rs = append(rs, r)
    } else {
      replacement, err := replacer(r)
      if err != nil {
        return "", err
      }
      rs = append(rs, []rune(replacement)...)
    }
  }
  return string(rs), nil
}

func main() {
  replacers := []func(r rune) (string, error){
    // omit invalid runes
    func(_ rune) (string, error) { return "", nil },
    // replace with question marks
    func(_ rune) (string, error) { return "?", nil },
    // abort with error */
    func(r rune) (string, error) { return "", fmt.Errorf("invalid rune 0x%x", r) },
  }

  ss := []string{"Hello, World!", "Hello, 世界!"}
  for _, s := range ss {
    for _, r := range replacers {
      ascii, err := forceASCII(s, r)
      fmt.Printf("OK: %q → %q, err=%v\n", s, ascii, err)
    }
  }
  // OK: "Hello, World!" → "Hello, World!", err=<nil>
  // OK: "Hello, World!" → "Hello, World!", err=<nil>
  // OK: "Hello, World!" → "Hello, World!", err=<nil>
  // OK: "Hello, 世界!" → "Hello, !", err=<nil>
  // OK: "Hello, 世界!" → "Hello, ??!", err=<nil>
  // OK: "Hello, 世界!" → "", err=invalid rune 0x4e16
}

check this function

func UtftoAscii(s string) []byte {
    t := make([]byte, utf8.RuneCountInString(s))
    i := 0
    for _, r := range s {
        t[i] = byte(r)
        i++
    }
    return t
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM