我想知道为什么你不能做:
type Foo struct { A int }
type Bar Foo
foos := []Foo{Foo{1}, Foo{2}}
bars := []Bar(foos)
//cannot convert foos (type []Foo) to type []Bar
我发现这将需要运行时在片上执行循环以转换每个元素,这将是非惯用的Go。这很有道理。
然而,这可能不会被刚刚走样编译器解决Bar
的Foo
,所以在内部它们是相同的,他们使用相同类型的头底下?我猜答案虽然不是我好奇为什么。
这个:
[]Bar(foos)
是类型转换。根据规范,转换具有特定的规则:
在以下任何一种情况下,
x
可以将非恒定值转换为类型T
:
x
是分配给T
。x
的类型,并且T
具有相同的基础类型。x
的类型和T
是未命名的指针类型,它们的指针基类型具有相同的基础类型。x
的类型T
均为整数或浮点类型。x
的类型和T
都是复杂类型。x
是整数或字节或符文的片段,并且T
是字符串类型。x
是一个字符串,T
是字节或符文的一部分。
这里没有适用。为什么?
因为的基础类型[]Foo
与的基础类型不同[]Bar
。类型[]Foo
值不能分配给类型变量[]Bar
,请参见此处的可分配性规则。
的基础类型Foo
与的基础类型Bar
相同,但不适用于元素类型为Foo
和的切片Bar
。
因此,以下工作原理:
type Foo struct{ A int }
type Foos []Foo
type Bars Foos
func main() {
foos := []Foo{Foo{1}, Foo{2}}
bars := Bars(foos)
fmt.Println(bars)
}
输出(在Go Playground上尝试):
[{1} {2}]
注意,由于实际内存中的表示Foo
和Bar
是相同的(由于底层类型Bar
是Foo
使用包),在此情况下unsafe
可以通过“视图”的值[]Foo
作为值[]Bar
:
type Foo struct{ A int }
type Bar Foo
func main() {
foos := []Foo{Foo{1}, Foo{2}}
bars := *(*[]Bar)(unsafe.Pointer(&foos))
fmt.Println(bars)
fmt.Printf("%T", bars)
}
这:*(*[]Bar)(unsafe.Pointer(&foos))
表示取的地址foos
,将其转换为unsafe.Pointer
(根据规范可以将所有指针转换为unsafe.Pointer
),然后将Pointer
其转换为*[]Bar
(再次根据规范Pointer
可以将其转换为任何其他指针类型),然后将该指针取消引用(*
运算符),因此结果是[]Bar
在输出中可以看到的type值。
输出(在Go Playground上尝试):
[{1} {2}]
[]main.Bar
笔记:
引用的软件包文档unsafe
:
不安全的软件包包含绕过Go程序的类型安全的操作。
导入不安全的软件包可能是不可移植的,并且不受Go 1兼容性准则的保护。
这是什么意思?这意味着您不应该usafe
每次都使用包来简化生活。您仅应在特殊情况下使用它,否则将使您的程序确实非常缓慢和复杂。
在您的程序中,情况并非如此,因为我提出了一个仅需一点重构(Foos
并且Bars
是切片)的工作示例。
unsafe
绕过Go的类型安全。这是什么意思?如果您要更改的类型foos
(例如,大幅度地更改foos := "trap!"
),您的程序仍会编译并运行,但是很可能会发生运行时恐慌。使用它们usafe
会丢失编译器的类型检查。
如果您使用我的其他提案(Foos
和Bars
),则会在编译时检测到此类更改/错别字。
问题内容: 我有一个子过程命令,输出一些字符,例如’\ xf1’。我正在尝试将其解码为utf8,但出现错误。 上面抛出: 当我使用’latin-1’时它可以工作,但是utf8也不能工作吗?我的理解是latin1是utf8的子集。 我在这里想念什么吗? 编辑: 问题答案: 您已经将Unicode与UTF-8混淆了。Latin-1是Unicode的子集,但不是UTF-8的子集。 避免像瘟疫一样思考各个
问题内容: 考虑以下: 我一直在寻找背后的逻辑,但是没有运气。值得一提的是,如果将结构更改为类,则效果很好。 总是可以添加一种解决方法,并将fooArray的每个对象映射为强制类型,将它们转换为Any类型,但这不是这里的问题。我正在寻找一种解释,为什么会这样。 有人可以解释一下吗? 问题答案: Swift 3更新 从Swift 3(特别是Xcode 8 beta 6附带的内部版本)开始,集合类型现
问题内容: 我刚开始使用Go,所以这很明显。编译器不允许以下代码:(http://play.golang.org/p/3sTLguUG3l) 错误是: 从规格上看,[] string看起来与[] Card不是相同的基础类型,因此无法进行类型转换。 确实是这样,还是我错过了什么? 如果是这样,为什么会这样呢?假设在一个非宠物示例程序中,我输入了一个字符串切片,是否可以将其“投射”到Card切片中,或
问题内容: 一个激励人的例子: 实施各种调度“策略”,对“作业”列表进行排序。 一种非常简单的策略是首先执行最短的作业(不考虑其权重/优先级)。 嗯,这种策略只不过是对job.length进行排序,因此让我们使用sort包。定义一个自定义类型,并实现sort.Interface … 好了,现在回到我们的简单策略… 嗯… 问题答案: 首先, 即使您使用like ,也看不到任何定义 。 我认为您的意思
问题内容: 目前,我这样做是为了将CGO的double数组转换为float64的一部分: 是否有一种不太麻烦的方式来做相同的事情?我想这也可以看作是Go中不同类型的切片/数组之间进行转换的一种通用方法。 问题答案: 您具有执行此操作的正常和安全的方法: 或者,您可以不方便地作弊并执行以下操作: 如果和是相同的基础类型,我们可以使用指向C.double数组的指针,不安全地将其强制转换为相同大小的fl
我正在尝试创建一个基本的谷歌地图android应用程序。就在我创建项目并获得API密钥之后,我就收到了这个错误。 “错误:不兼容类型:片段无法转换为SupportMapFragment” 行:SupportMapFragment mapFragment=(SupportMapFragment)getSupportFragmentManager().findFragmentByID(r.id.map