英文:
Duck typing in Go
问题
[]myint
无法传递给Join
,因为它不是fmt.Stringer
类型,所以我必须写成:
parts := []fmt.Stringer{myint(1), myint(5), myint(6)}
但是如果我需要在另一个操作中使用parts
,其中的值必须是整数,我应该将myint
的切片转换为Stringer
的切片吗?
英文:
I want to write a Join
function that takes arbitrary objects with a String()
method:
package main
import (
"fmt"
"strings"
)
type myint int
func (i myint) String() string {
return fmt.Sprintf("%d", i)
}
func main() {
parts := []myint{myint(1), myint(5), myint(6)}
fmt.Println(Join(parts, ", "))
}
func Join(parts []fmt.Stringer, sep string) string {
stringParts := make([]string, len(parts))
for i, part := range(parts) {
stringParts [i] = part.String()
}
return strings.Join(stringParts , sep)
}
http://play.golang.org/p/EhkbyibzHw
[]myint
cannot be passed to Join
, because it is not of type fmt.Stringer
, so I have to write:
parts := []fmt.Stringer{myint(1), myint(5), myint(6)}
But what if I need parts
for another operation where the values have to be ints? Should I cast a slice of myint
to a slice of Stringer
then?
答案1
得分: 6
在Go语言中,没有强制类型转换,只有类型转换。但是,从具体的非接口类型的切片到接口类型的切片的转换是不可能的,除非在循环中显式地进行转换。原因是,例如在你的情况下,[]myint
的底层数组与[]fmt.Stringer
的内存布局不同。(相关FAQ)
另外,你不必写成:
parts := []myint{myint(1), myint(5), myint(6)}
以下写法也可以:
parts := []myint{1, 5, 6}
英文:
> Q: Should I cast a slice of myint
to a slice of Stringer
then?
There are no casts in Go - only conversions. But conversion from a slice of concrete, non interface type to a slice of interface type is not possible, except by doing it explicitly in a loop. The reason is that, as for example in your case, the []myint
backing array has a different memory layout than []fmt.Stringer
has. (Related FAQ)
On a side note, you don't have to write:
parts := []myint{myint(1), myint(5), myint(6)}
This should work identically:
parts := []myint{1, 5, 6}
答案2
得分: 1
将Join函数改为
func Join(sep string, parts ...fmt.Stringer) string {
}
会使得代码更加简洁:
package main
import (
"fmt"
"strings"
)
type myint int
func (i myint) String() string {
return fmt.Sprintf("%d", i)
}
type myfloat float32
func (f myfloat) String() string {
return fmt.Sprintf("%0.2f", f)
}
func main() {
fmt.Println(Join(", ", myint(3), myfloat(3.5543)))
}
func Join(sep string, parts ...fmt.Stringer) string {
stringParts := make([]string, len(parts))
for i, part := range parts {
stringParts[i] = part.String()
}
return strings.Join(stringParts, sep)
}
英文:
Change the Join function to
func Join(sep string, parts ...fmt.Stringer) string {
}
makes it a lot easier:
package main
import (
"fmt"
"strings"
)
type myint int
func (i myint) String() string {
return fmt.Sprintf("%d", i)
}
type myfloat float32
func (f myfloat) String() string {
return fmt.Sprintf("%0.2f", f)
}
func main() {
fmt.Println(Join(", ", myint(3), myfloat(3.5543)))
}
func Join(sep string, parts ...fmt.Stringer) string {
stringParts := make([]string, len(parts))
for i, part := range parts {
stringParts[i] = part.String()
}
return strings.Join(stringParts, sep)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论