您可以键入assert匿名结构吗?

时间:2018-08-21 06:38:50

标签: go struct types casting

我想做这样的事情:

type Struct1 struct {
    var1 int
}

type i interface {
    display()
}

func (s Struct1) display() {
    fmt.Println(s.var1)
}

func check(i interface{}) {
    i.(Struct1).display()
}

func main() {
    data := struct {
        int
    }{
        2,
    }

    check(interface{}(data))
}

我在外部依赖项中有一个函数,该函数接受并返回interface {}类型。该函数类型声明一个struct(比方说Struct1)。该结构具有未导出到的字段,因此我无法创建该结构的实例以传递给该函数。我知道它具有哪些字段,它们的名称和类型。是否可以发送不是可以声明为Struct1类型的Struct1类型的数据。

2 个答案:

答案 0 :(得分:3)

  

您可以键入断言一个匿名结构吗?

当然可以!但是有局限性。

一些可行的方法:

  1. 声明匹配的匿名结构:

    x := interface{}(struct { Count int }{Count: 5})
    fmt.Printf("x's count: %d\n", x.(struct{Count int}).Count)
    

    Playground

  2. 声明接口:

        type Fooer interface {
        Foo()
    }
    
    type X struct {}
    
    func (x X) Foo() { fmt.Printf("X Fooed\n") }
    
    
    func main() {
        x := interface{}(struct { X }{ X{} }) // An anonymous struct which embeds X
        x.(Fooer).Foo()
    }
    

    Playground

一些不起作用的东西:

  1. 使用未导出的字段从另一个程序包向匹配的匿名结构声明。

    x := url.UserPassword("foo","bar")
    fmt.Printf("Username: %s\n", x.(struct{username string; password string; passwordSet bool}).username)
    

    Playground

答案 1 :(得分:0)

您无法在特定情况下尝试做什么。尽管Struct1和您的匿名结构具有相同的布局,但它们对于Go编译器而言是不同的类型。想想时间。例如,Duration实际上只是一个int64,但您不能互换使用它们。这是在Go中故意完成的。其他语言(例如C)允许您进行各种转换和强制转换,并且很少会出现编译器错误。已经证明这是程序员错误的根源,因此在Go中的处理方式有所不同。

为了完整起见,仍然为您提供问题的“解决方案”,以下是使用类似C的不安全强制转换将您的匿名结构转换为Struct1的版本:

package main

import (
    "fmt"
    "unsafe"
)

type S struct {
    i int
}

type I interface {
    display()
}

func (s S) display() {
    fmt.Println(s.i)
}

func check(i interface{}) {
    i.(S).display()
}

func main() {
    data := struct{ int }{2}
    // check(data) this will not work
    check(*((*S)(unsafe.Pointer(&data))))
}