如何迭代 charmap.All 中的 Charmaps 列表并比较名称?

huangapple go评论89阅读模式
英文:

How to iterate list of Charmaps in charmap.All and compare names?

问题

我想写一个小的命令行实用程序来解码/编码文本流,类似于 iconv,但是使用 Go 语言。用户将提供编码器和解码器的名称,实用程序将使用 charmap.All 来检查它们是否有效,然后再尝试解码/编码流。

我可以遍历 charmap.All 并打印名称,如下所示:

for _, cmap := range charmap.All {
	fmt.Println(cmap)
}

我可以将我的 cmap 变量与已知的 Charmap 进行比较:

if cmap == charmap.ISO8859_1 {
	fmt.Println(charmap.ISO8859_1.String())
}

但是我不知道如何进行下一步,这似乎非常接近(而且很简单):

var encoder string
flag.StringVar(&encoder, "encoder", "ISO 8859-1", "name of encoder")
flag.Parse()

for _, cmap := range charmap.All {
	if cmap.String() == encoder {
		// 根据用户的输入进行编码
	}
}

encoding/charmap API 的帮助下,这种操作是否可行?

另外,为什么我的 cmap 变量和 charmap.ISO8859_1 是等价的(在 cmap == charmap.ISO8859_1 的示例中),但是 cmap 实际上是一个 Encoding 接口,我无法进行转换:

charmap.Charmap(cmap).String()无法将类型为 encoding.Encoding 的 cmap 转换为类型 charmap.Charmap

我对 Go 语言还不太熟悉,对于类型和接口之间的这些差异和等价性还不太理解。

英文:

I'd like to write a little command-line utility to decode/encode streams of text, like iconv, but in Go. The user will provide the encoder and decoder names and the utility will check them against charmap.All to make the user args are valid before trying to decode/encode the stream.

I can iterate charmap.All and print the names like:

for _, cmap := range charmap.All {
	fmt.Println(cmap)
}

I can compare my cmap var to a known Charmap:

if cmap == charmap.ISO8859_1 {
	fmt.Println(charmap.ISO8859_1.String())
}

But I don't know how to do the next step, which seems so tantalizingly close (and easy):

var encoder string
flag.StringVar(&encoder, "encoder", "ISO 8859-1", "name of encoder")
flag.Parse()

for _, cmap := range charmap.All {
	if cmap.String() == encoder {
		// encode based on user's input
	}
}

Is that possible, given the encoding/charmap API?

Also, how is it that my cmap var and charmap.ISO8859_1 are equivalent (in the cmap == charmap.ISO8859_1 example), but cmap is really an Encoding interface, and I cannot convert:

charmap.Charmap(cmap).String() → cannot convert cmap (type encoding.Encoding) to type charmap.Charmap

I'm still pretty new to Go, and don't fully understand these differences and equivalencies in types and interfaces.

答案1

得分: 3

你可以按如下方式进行拆解,charmap.All 是一个 Encoding 接口的切片,可以使用 range 循环进行迭代。

相等性成立是因为 Charmap 类型实现了该接口,也就是说每个 charmap 类型都会有一个定义了 NewDecoder()NewEncoder() 方法实现的接口。根据语言规范,如果一个结构体实现了一个接口,它们可以进行比较(参见比较运算符)。

> 当非接口类型 X 的值 x 和接口类型 T 的值 t 可比较时,当类型 X 可比较且 X 实现了 T 时,它们是可比较的。如果 t 的动态类型与 X 相同且 t 的动态值等于 x,则它们相等。

通过上述推断,我们可以理解 func (*Charmap) StringCharmap 结构体类型的方法,而不是接口的方法。因此,正确的做法是对接口值进行类型断言,然后在其上调用字符串函数。

for _, enc := range charmap.All {
    cmap, ok := enc.(*charmap.Charmap)
    if ok && cmap.String() == encoder {
        // 根据用户的输入进行编码
    }
}
英文:

You can break it down as follows, charmap.All is a slice of Encoding interfaces, which can be iterated using a range loop.

The equality works because the type Charmap, implements the interface, i.e. each charmap type will have a NewDecoder() and a NewEncoder() method implementation defined. By the language specification, if a struct implements an interface, they can be compared (See Comparison operators)

> A value x of non-interface type X and a value t of interface type T are comparable when values of type X are comparable and X implements T. They are equal if t's dynamic type is identical to X and t's dynamic value is equal to x

With the above inference, we can understand that the func (*Charmap) String is a method on the Charmap struct type and not on the interface. So the right way to do this, would be to Type assert your interface value and then call the string function on the same.

for _, enc := range charmap.All {
    cmap, ok := enc.(*charmap.Charmap)
    if ok && cmap.String() == encoder {
        // encode based on user's input
    }
}

huangapple
  • 本文由 发表于 2021年11月8日 18:04:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/69881690.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定