Go 如何从数据源读取unicode字符

Go 如何从数据源读取unicode字符,go,Go,下面的代码能够读取数据源(遵循所有读取规则),具有文本(大小为一个字节的UTF-8编码): 输出: $ $ $ go run src/../Main.go 3 bytes read, data:Hel 3 bytes read, data:lo 3 bytes read, data:Ama 3 bytes read, data:zin 3 bytes read, data:g W 3 bytes read, data:orl 2 bytes read, data:d! --end-of-fi

下面的代码能够读取数据源(遵循所有读取规则),具有文本(大小为一个字节的UTF-8编码):


输出:

$
$
$ go run src/../Main.go
3 bytes read, data:Hel
3 bytes read, data:lo 
3 bytes read, data:Ama
3 bytes read, data:zin
3 bytes read, data:g W
3 bytes read, data:orl
2 bytes read, data:d!
--end-of-file--
$
$

但上述代码无法读取文本(UTF-8编码的大小大于一个字节)的数据源,如下所示:

  src := MyStringData{str: "Hello Amazing World!学中文"} 
以下是输出:

$
$
$ go run src/../Main.go
3 bytes read, data:Hel
3 bytes read, data:lo 
3 bytes read, data:Ama
3 bytes read, data:zin
3 bytes read, data:g W
3 bytes read, data:orl
3 bytes read, data:d!�
3 bytes read, data:���
3 bytes read, data:���
2 bytes read, data:��
--end-of-file--
$
$

编辑:

根据对
strings.NewReader()
用法的注释,下面是修改后的代码:

// create data source
src := strings.NewReader("Hello Amazing World!学中文") // 学中文

// p := make([]byte, 3) // slice of length `3`

// read `src` until an error is returned
for {
    // read `p` bytes from `src`
    ch, n, err := src.ReadRune()
    // n, err := src.Read(p)
    fmt.Printf("%d bytes read, data:%c\n", n, ch)

    // handle error
    if err == io.EOF {
        fmt.Println("--end-of-file--")
        break
    } else if err != nil {
        fmt.Println("Oops! some error occured!", err)
        break
    }
}

如何在不拆分字符的情况下读取unicode字符(例如
Read
调用中使用,例如
bufio.Reader
ReadRune
函数,或带有扫描函数的
bufio.Scanner
,该函数只返回一个或多个完整的符文(使用
DecodeRune
FullRune
from进行验证,就像stdlib
bufio.ScanRunes
所做的那样)


你可以通过在一个片段中缓冲不完整的符文并在其上附加连续的读取来完成,但这只是重复了扫描器的功能。

标准的
字符串有什么问题。Reader
?一般来说,你不能阻止read返回部分代码点。Th@MuffinTop无法阻止读取返回部分代码点……这不是一个糟糕的抽象吗?
io.Reader
不是解码unicode的抽象,它是读取数据的抽象,显然不总是utf8编码的。@JimB如何使用
strings.Reader
来解决这个问题?
// create data source
src := strings.NewReader("Hello Amazing World!学中文") // 学中文

// p := make([]byte, 3) // slice of length `3`

// read `src` until an error is returned
for {
    // read `p` bytes from `src`
    ch, n, err := src.ReadRune()
    // n, err := src.Read(p)
    fmt.Printf("%d bytes read, data:%c\n", n, ch)

    // handle error
    if err == io.EOF {
        fmt.Println("--end-of-file--")
        break
    } else if err != nil {
        fmt.Println("Oops! some error occured!", err)
        break
    }
}