在 Go 中封装结构



我是Go的新手。我已经读到Go中的封装是在包级别。我有一个简单的网络控制器用例。我有一个结构,它作为 JSON 对象进入,并被解编成结构类型。

type User struct{
    Name String `json:"name"`
    //Other Variables
}

现在,可以通过 json 将 json 解编为用户结构类型。Unmarshal([]byte(。但是,此用户结构也可用于其他包。如何确保其他包只能访问与用户相关的方法。

我能想到的一个解决方案:

type User struct{
    name String
}
type UserJSON struct{
    Name String `json:"name"`
}
func DecodeJSONToUser(rawJSON []byte) (User,error) {
    var userJSON UserJSON
    err := json.Unmarshal(rawJSON,&userJSON)
    //Do error handling
    return User{name:userJSON.Name},nil
}

有没有一种GOish方法可以实现这一目标?

您可以将包

本地结构公共字段一起使用,以便此结构在包外部不可见。然后你可以让这个结构满足一些公共接口,你就有了完美的解耦:

package user
import "encoding/json"
type User interface {
    Name() string
}
type user struct {
    Username string `json:"name"`
}
func (u *user) Name() string {
    return "Mr. " + u.Username
}
func ParseUserData(data []byte) (User, error) {
    user := &user{}
    if err := json.Unmarshal(data, user); err != nil {
        return nil, err
    }
    return user, nil
}

以及相应的测试:

package user_test
import (
    "testing"
    "github.com/teris-io/user"
)
func TestParseUserData(t *testing.T) {
    data := []byte("{"name": "Uncle Sam"}")
    expected := "Mr. Uncle Sam"
    if usr, err := user.ParseUserData(data); err != nil {
        t.Fatal(err.Error())
    } else if usr.Name() != expected {
        t.Fatalf("expected %s, found %s", expected, usr.Name())
    }
}

➜ 用户 git:(主( ✗ 去测试 github.com/teris-io/user

正常 github.com/teris-io/user 0.001s

您还可以在取消编组后将包本地对象转换为某个公共对象。

注意:其中一条评论提到由于名称冲突(结构上的字段user.Name和接口上的方法User.Name(,接口需要具有不同的方法名称是多么可惜。这不是必需的,上面的代码也相应修改了:内部结构上的字段可以与 JSON 中的字段具有不同的名称,相应的注释定义了映射。

最新更新