简体   繁体   中英

non exported fields when extending a struct from another package

I am using go-simplejson in a small toy project (acutally my first go project ever). In this project I need to extend the simplejson package:

simplejson introduces a small struct (with some helpful methods) with a constructor function:

type Json struct {
    data interface{}
}

// NewJson returns a pointer to a new `Json` object
// after unmarshaling `body` bytes
func NewJson(body []byte) (*Json, error) {
    j := new(Json)
    err := j.UnmarshalJSON(body)
    if err != nil {
        return nil, err
    }
    return j, nil
}

In my project, i want to sync some xml data to CouchDB. For this I would love to make a new constructor, where I deliver the decoded xml (type interface{}) directly to the Json object, then marshal it to JSON.

This is trivial:

func NewJsonFromData(data interface{}) *Json {
    return &Json{data}
}

now since this is some kind of "hack", I want to avoid forking go-simplejson and implement it in go-simplejson, because I would "pollute" the general package. I would like to do this in my own little toy package. And here is where te trouble begins:

the data field is unexported and not visible outside the package... so putting this function declaration in my other package like so:

func NewJsonFromData(data interface{}) *simplejson.Json {
    return &simplejson.Json{data}
}

doesn't work, it gives the following compile error:

implicit assignment of unexported field 'data' in simplejson.Json literal

also doing

type Json struct {
    simplejson.Json
}

in my own package doesn't work, i cannot set the data field in the constructor of my own Json struct that composes simplejson.Json, since its unexported (it would obviously work if the field would be called "Data".

making a file in my own package folder having

package simplejson

is not accepted, since go forces you to keep all the files of a package in one folder.

  1. Is it correct that it is simply impossible in go to extend package functionality if the developer decided to not export struct fields? (I see the reason why one would do that, on the other hand, I would like to do it, since its "only" a toy example :) )

  2. If it's possible, whats the best way to do it?

This the same in all languages, private fields are not accessible outside their scope.

That being said if you have the interface already why not use the standard JSON library which has an marshal function which takes an interface directly without having to set to a field.

package main

import (
    "encoding/json"
)

func main() {
    v := ....
    jsonBytes, err := json.Marshal(v)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM