Go语言 你能输入assert一个匿名结构吗?

kqqjbcuj  于 2023-02-17  发布在  Go
关注(0)|答案(2)|浏览(174)

我想做这样的事情:

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{}类型。该函数类型Assert一个struct(比方说Struct 1)。该struct具有未导出到的字段。我无法创建它的示例以传递给该函数。我知道它具有哪些字段,它们的名称和类型。是否可以发送可以Assert为Struct 1类型的非Struct 1类型的数据。

goqiplq2

goqiplq21#

你能输入assert一个匿名结构吗?
你当然可以!但是有限制。
以下是一些有用的方法:
1.Assert到匹配的匿名结构:

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

Playground.
1.Assert到接口:

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.Assert到来自另一个包的匹配匿名结构,其中包含未导出的字段。

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

Playground.

fzsnzjdm

fzsnzjdm2#

在特定的情况下,你尝试做的事情是不可能的,即使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))))
}

相关问题