【问题标题】:Type Assertion using identical structs between packages类型断言在包之间使用相同的结构
【发布时间】:2018-12-14 19:57:41
【问题描述】:

我很难理解 Go 中的某些类型断言,以及为什么下面的代码不起作用并导致恐慌。

panic:接口转换:接口 {} 是 []db.job,而不是 []main.job

主要:

/*stackTypeAssert.go
> panic: interface conversion: interface {} is []db.job, not []main.job
*/

package main

import (
    "fmt"
    "stackTypeAssert/db"
)

type job struct {
    ID     int
    Status string
}

type jobs interface{}

func main() {
    jobTable := db.GetJobs()
    fmt.Println(jobTable) // This works: [{1 pending} {2 pending}]

    //Type Assertion
    var temp []job
    //panic: interface conversion: interface {} is []db.job, not []main.job
    temp = jobTable.([]job)
    fmt.Println(temp)
}

包数据库:

/*Package db ...
panic: interface conversion: interface {} is []db.job, not []main.job
*/
package db

//GetJobs ...
func GetJobs() interface{} {
    //Job ...
    type job struct {
        ID     int
        Status string
    }
    task := &job{}
    var jobTable []job
    for i := 1; i < 3; i++ {
        *task = job{i, "pending"}
        jobTable = append(jobTable, *task)
    }
    return jobTable
}

【问题讨论】:

    标签: go struct interface type-assertion


    【解决方案1】:

    Import declarations 的 go lang 规范中,它被描述为:-

    PackageName 用于限定标识符以访问导出的 导入源文件中包的标识符。它是 在文件块中声明。如果省略 PackageName,则默认为 到导入的包子句中指定的标识符 包裹。如果出现显式句点 (.) 而不是名称,则所有 在该包的包中声明的包的导出标识符 块将在导入源文件的文件块中声明,并且 必须在没有限定符的情况下访问。

    正如错误所说:-

    恐慌:接口转换:接口 {} 是 []db.job,而不是 []main.job

    你应该使用 db 包的结构,通过将其导入 main 来创建临时变量,因为返回的值是包装结构 db.jobs 而不是 main.jobs 的接口

    package main
    
    import (
        "fmt"
        "stackTypeAssert/db"
    )
    
    type job struct {
        ID     int
        Status string
    }
    
    type jobs interface{}
    
    func main() {
        jobTable := db.GetJobs()
        fmt.Println(jobTable) // This works: [{1 pending} {2 pending}]
    
        // create a temp variable of []db.Job type
        var temp []db.Job
        // get the value of interface returned from `GetJobs` function in db package and then use type assertion to get the underlying slice of `db.Job` struct.
        temp = jobTable.(interface{}).([]db.Job)
        fmt.Println(temp)
    }
    

    db 包文件中定义GetJobs() 函数之外的结构,并通过将结构转换为uppercase 使其可导出。

    package db
    // make it exportable by converting the name of struct to uppercase
    type Job struct {
        ID     int
        Status string
    }
    
    //GetJobs ...
    func GetJobs() interface{} {
        task := &Job{}
        var jobTable []Job
        for i := 1; i < 3; i++ {
            *task = Job{i, "pending"}
            jobTable = append(jobTable, *task)
        }
        return jobTable
    }
    

    输出

    [{1 pending} {2 pending}]
    [{1 pending} {2 pending}]
    

    有关导出标识符的更多信息,您可以查看此链接Exported functions from another package

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-30
      • 1970-01-01
      • 2018-01-09
      相关资源
      最近更新 更多