Golang:在结构切片之间进行类型转换

时间:2014-07-08 21:53:58

标签: struct go type-conversion

此问题遵循another question of mine

我在下面的测试代码中尝试将res转换为ListSociete并没有完全解决问题:

import (
    "errors"
    "fmt"
    "github.com/jmcvetta/neoism"
)

type Societe struct {
    Name string
}

type ListSociete []Societe

func loadListSociete(name string) (ListSociete, error) {
    db, err := neoism.Connect("http://localhost:7474/db/data")
    if err != nil {
        return nil, err
    }
    res := []struct {
        Name string `json:"a.name"`
    }{}
    cq := neoism.CypherQuery{
        Statement: `
            MATCH (a:Societe)
            WHERE a.name = {name}
            RETURN a.name
            `,
        Parameters: neoism.Props{"name": name},
        Result:     &res,
    }
    db.Cypher(&cq)
    if len(res) == 0 {
        return nil, errors.New("Page duz not exists")
    }
    r := res[0]
    return ListSociete(res), nil
}

[]struct{Name string}[]struct{Name string json:"a.name" }有什么不同?

或者ListSociete与[]struct{Name string}不同?

感谢。

2 个答案:

答案 0 :(得分:8)

您目前正在处理两种不同的类型:

type Societe struct {
    Name string
}

和匿名者:

struct {
    Name string `json:"a.name"`
}

如果不是标签,这两个将是相同的。 Go Specifications 状态(我的重点):

  

如果两个结构类型具有相同的字段序列,则它们是相同的   相应的字段具有相同的名称,相同的类型,和相同的标记。   两个匿名字段被认为具有相同的名称。小写字段名称   从不同的包装总是不同的。

所以,你不能在两者之间进行简单的转换。此外,您正在转换这两种类型的切片这一事实会导致转换出现问题。我可以为您看到两个选项:

通过迭代复制:

这是安全且推荐的解决方案,但它也更加冗长和缓慢。

ls := make(ListSociete, len(res))
for i := 0; i < len(res); i++ { 
    ls[i].Name = res[i].Name
}
return ls, nil

不安全的转化:

由于两种类型都具有相同的基础数据结构,因此可以进行不安全的转换 这可能会在以后爆炸。警告!

return *(*ListSociete)(unsafe.Pointer(&res)), nil

游乐场示例: http://play.golang.org/p/lfk7qBp2Gb

答案 1 :(得分:0)

所以,经过一些测试,我发现了什么:

ListSociete定义为......

type Societe struct {
    Name string `json:"a.name"`
}

type ListSociete []Societe

与此不同:

type ListSociete []struct {
    Name string `json:"a.name"`
}

这第二个解决方案有效,而第一个解决方案没有。

所以我假设在具有不同标签的类型之间真的没有办法转换(直接没有编写显式循环)?

在这种情况下,我肯定会使用循环,因为直接在类型中使用标记(参见上面的第二个解决方案)会使我的代码难以理解且无法使用,我也真的不知道我会弄乱什么使用不安全的转换方法。所以感谢您确认不同类型的不同标签。