英文:
How to concatenate Aliased Types (of consts) into strings.Join()
问题
我有一个允许传入值切片的包/API。例如:
type ConstType string
const (
T_Option1 ConstType = "OPTION-1"
T_Option2 ConstType = "OPTION-2"
T_Option3 ConstType = "OPTION-3"
)
注意这个类型是字符串的别名。
我遇到的问题是,我无法将这个类型别名的切片转换或推断为[]string
切片。
type constTypes struct {
types []ConstType
}
func (s *constTypes) SetConstTypes(types []ConstType) {
s.types = types
}
func (s *constTypes) String() string {
// 这会生成一个编译错误,因为[]ConstType不是[]string。
//
// 但是,你可以看到,ConstType的类型是字符串
//
return strings.Join(s.types, ",")
}
我在playground中放了一个完整的示例来展示:
http://play.golang.org/p/QMZ9DR5TVR
我知道Go的解决方案是将其转换为该类型(显式类型转换,我喜欢这个规则!)。我只是无法弄清楚如何将类型的切片转换为[]string - 而不需要循环遍历集合。
我喜欢Go的原因之一是强制类型转换,比如:
c := T_OPTION1
v := string(c)
fmt.Println(v)
Play: http://play.golang.org/p/839Qp2jmIz
不过,我不确定如何在切片中做到这一点而不需要循环。我必须循环吗?
虽然循环遍历集合不是什么大问题,因为最多只会有5到7个选项集。但是,我仍然觉得应该有一种可转换的方法来做到这一点。
英文:
I have an package/API that allows for passing in a slice of values. For example:
type ConstType string
const (
T_Option1 ConstType = "OPTION-1"
T_Option2 ConstType = "OPTION-2"
T_Option3 ConstType = "OPTION-3"
)
Notice how this type is an alias of string.
Where I am running into a what-i-think-is-non-idomatic-step is that I can't cast or infer a slice of this type alias to a []string
slice.
type constTypes struct {
types []ConstType
}
func (s *constTypes) SetConstTypes(types []ConstType) {
s.types = types
}
func (s *constTypes) String() string {
// this generates a compile error because []ConstType is not
// and []string.
//
// but, as you can see, ConstType is of type string
//
return strings.Join(s.types, ",")
}
I put this together in the playground to show a complete example:
http://play.golang.org/p/QMZ9DR5TVR
I know the Go solution is to cast it to the type (explicit Type casting, love the rule!). I just can't figure out how to cast a slice of types to []string - without looping through the collection.
One of the reasons I like Go is the enforcement of type casting, like:
c := T_OPTION1
v := string(c)
fmt.Println(v)
Play: http://play.golang.org/p/839Qp2jmIz
Though, I am unsure how to do this across the slice without looping. Must I loop?
Given, looping through the collection is not a big deal since there will only be 5 to 7 options max set. But still, I feel there should be a cast-able way to do this.
答案1
得分: 1
如@Not_a_Golfer所指出的,你应该通过循环遍历constType
的切片并构建一个新的string
切片。这种方法的缺点是需要复制每个元素(这可能对你来说重要或不重要)。
还有另一种解决方案,但它涉及到标准库中的unsafe
包。我修改了你在Go Playground上发布的示例(新链接是http://play.golang.org/p/aLmvSraktF)。
package main
import (
"fmt"
"strings"
"unsafe"
)
type ConstType string
const (
T_Option1 ConstType = "OPTION-1"
T_Option2 ConstType = "OPTION-2"
T_Option3 ConstType = "OPTION-3"
)
// constTypes is an internal/private member handling
type constTypes struct {
types []ConstType
}
func (s *constTypes) SetConstTypes(types []ConstType) {
s.types = types
}
func (s *constTypes) String() string {
// Convert s.types to a string slice.
var stringTypes []string // Long varibale declaration style so that you can see the type of stringTypes.
stringTypes = *(*[]string)(unsafe.Pointer(&s.types))
// Now you can use the strings package.
return strings.Join(stringTypes, ",")
}
func main() {
types := constTypes{}
// a public method on my package's api allows this to be set via a slice:
types.SetConstTypes([]ConstType{T_Option1, T_Option2, T_Option3})
fmt.Println(types.String())
}
希望对你有帮助!
英文:
As @Not_a_Golfer points out, you should really be looping through the slice of constType
and building up a new slice of string
. This has the disadvantage of copying each element (which may or may not matter to you).
There is another solution, although it involves the unsafe
package from the standard library. I've modified the example that you posted to the Go Playground (new link is http://play.golang.org/p/aLmvSraktF)
package main
import (
"fmt"
"strings"
"unsafe"
)
type ConstType string
const (
T_Option1 ConstType = "OPTION-1"
T_Option2 ConstType = "OPTION-2"
T_Option3 ConstType = "OPTION-3"
)
// constTypes is an internal/private member handling
type constTypes struct {
types []ConstType
}
func (s *constTypes) SetConstTypes(types []ConstType) {
s.types = types
}
func (s *constTypes) String() string {
// Convert s.types to a string slice.
var stringTypes []string // Long varibale declaration style so that you can see the type of stringTypes.
stringTypes = *(*[]string)(unsafe.Pointer(&s.types))
// Now you can use the strings package.
return strings.Join(stringTypes, ",")
}
func main() {
types := constTypes{}
// a public method on my package's api allows this to be set via a slice:
types.SetConstTypes([]ConstType{T_Option1, T_Option2, T_Option3})
fmt.Println(types.String())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论