How to concatenate Aliased Types (of consts) into strings.Join()

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

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())
}

huangapple
  • 本文由 发表于 2014年12月5日 00:35:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/27299180.html
匿名

发表评论

匿名网友

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

确定