dsfsfdsf4544 2015-03-13 11:42
浏览 257
已采纳

将字符串切片转换为自定义类型的切片

I'm quite new to Go, so this might be obvious. The compiler does not allow the following code: (http://play.golang.org/p/3sTLguUG3l)

package main

import "fmt"

type Card string
type Hand []Card

func NewHand(cards []Card) Hand {
    hand := Hand(cards)
    return hand
}

func main() {
    value := []string{"a", "b", "c"}
    firstHand := NewHand(value)
    fmt.Println(firstHand)
}

The error is: /tmp/sandbox089372356/main.go:15: cannot use value (type []string) as type []Card in argument to NewHand

From the specs, it looks like []string is not the same underlying type as []Card, so the type conversion cannot occur.

Is it, indeed, the case, or did I miss something?

If it is the case, why is it so? Assuming, in a non-pet-example program, I have as input a slice of string, is there any way to "cast" it into a slice of Card, or do I have to create a new structure and copy the data into it? (Which I'd like to avoid since the functions I'll need to call will modify the slice content).

  • 写回答

3条回答 默认 最新

  • douguaidian8021 2015-03-13 13:00
    关注

    The underlying type of Card might be the same as the underlying type of string (which is itself: string), but the underlying type of []Card is not the same as the underlying type of []string (and therefore the same applies to Hand).

    You cannot convert a slice of T1 to a slice of T2, it's not a matter of what underlying types they have, if T1 is not identical to T2, you just can't. Why? Because slices of different element types may have different memory layout (different size in memory). For example the elements of type []byte occupy 1 byte each. The elements of []int32 occupy 4 bytes each. Obviously you can't just convert one to the other even if all values are in the range 0..255.

    But back to the roots: if you need a slice of Cards, why do you create a slice of strings in the first place? You created the type Card because it is not a string (or at least not just a string). If so and you require []Card, then create []Card in the first place and all your problems go away:

    value := []Card{"a", "b", "c"}
    firstHand := NewHand(value)
    fmt.Println(firstHand)
    

    Note that you are still able to initialize the slice of Card with untyped constant string literals because it can be used to initialize any type whose underlying type is string. If you want to involve typed string constants or non-constant expressions of type string, you need explicit conversion, like in the example below:

    s := "ddd"
    value := []Card{"a", "b", "c", Card(s)}
    

    If you have a []string, you need to manually build a []Card from it. There is no "easier" way. You can create a helper toCards() function so you can use it everywhere you need it.

    func toCards(s []string) []Card {
        c := make([]Card, len(s))
        for i, v := range s {
            c[i] = Card(v)
        }
        return c
    }
    

    Some links for background and reasoning:

    Go Language Specification: Conversions

    why []string can not be converted to []interface{} in golang

    Cannot convert []string to []interface {}

    What about memory layout means that []T cannot be converted to []interface in Go?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置