I am new to Go and am unsure about how to approach this problem. In OOP terms, I have a base class of Animal and two subclasses of Cat and Dog. I want to specify a ToJson method for Animal which will work for all animals.
My problem is that when I call dog.ToJson() I only get the Dog properties of dog and none of the Animal properties.
How can I make ToJson work as expected (ie with recursion)?
edit: Changed code to reflect suggestions in answer by lbonn, which I could not get to work how I want it to.
edit2: consistency in question following code change
package main
import (
"encoding/json"
"fmt"
)
type Animal struct {
Name string
}
type Cat struct {
CatProperty int64
Animal
}
type Dog struct {
DogProperty int64
Animal
}
func ToJson(i interface{}) []byte {
data,err := json.Marshal(i)
if err != nil {
panic("???")
}
return data
}
func main() {
dog := Dog{}
dog.Name = "rex"
dog.DogProperty = 2
fmt.Println(string(ToJson(dog)))
// Prints {"DogProperty":2}
// I want it to print {"Name":"rex","DogProperty":2}
}
Json encoding of anonymous fields was dropped from go 1. Hopefully it will be back in go 1.1. See https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/jYMHbEv44r4 for more details.
So the best you can get with the standard library right now (with go 1) is http://play.golang.org/p/LncNFeN8ys
You can always use skelterjohn's patch https://github.com/skelterjohn/json/ to support anonymous fields till go 1.1 is released.
Or use tip, installing from source that has this issue fixed. see https://codereview.appspot.com/6460044
Here, the ToJson method applies to the anonymous field Animal of Dog. The call d.ToJson is only a visibility shortcut to d.Animal.ToJson.
GoLang Tutorials: Anonymous fields in struct
Here, I would write a function instead of a method (a simple wrapper around Marshal):
func ToJson(i interface{}) []byte {
data,err := json.Marshal(i)
if err != nil {
panic("???")
}
return data
}
This is not specific to animals or dogs but it doesn't really need to.
More generally, there is no real notion of inheritance in go. The object paradigm used in the language is quite different from mainstream OOP, like in Java or C++. The Go FAQ provides some good clarifications about it.
Related
Could anybody help me to clarify in which situations is better to use functions as the struct fields and when as the methods of struct?
A field of function type is not a method, so it's not part of the method set of the struct type. A "true" method declared with the struct type as the receiver will be part of the method set.
That being said, if you want to implement an interface, you have no choice but to define "true" methods.
Methods are "attached" to concrete types and cannot be changed at runtime. A field of function type may be used to "mimic" virtual methods, but as said above, this is not a method. A field of function type may be reassigned at runtime.
Like in this example:
type Foo struct {
Bar func()
}
func main() {
f := Foo{
Bar: func() { fmt.Println("initial") },
}
f.Bar()
f.Bar = func() { fmt.Println("changed") }
f.Bar()
}
Which outputs (try it on the Go Playground):
initial
changed
Fields of function type are often used to store callback functions. Examples from the standard lib are http.Server and http.Transport.
I have a function which currently doesn't receive a bool parameter, but then calls another function with a hardcoded bool. We need to remove the hardcoded call and allow a bool to be passed.
I first thought I could try some default parameter - my google searches resulted in that Go apparently doesn't support optional (resp. default) parameter.
So I thought I'd try function overloading.
I found this thread on reddit, which says that it works with a special directive since version 1.7.3:
https://www.reddit.com/r/golang/comments/5c57kg/when_did_function_overloading_get_slipped_in/
I am using 1.8, and still I couldn't get it to work.
I am not even sure I may be allowed to use that directive, but I was speculating that changing the function signature right away may be dangerous as I don't know who uses the function...
Anyway - even with //+overloaded it didn't work
Is there any "idiosyncratic" way or pattern to solve this problem in Go?
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
//result, err := anotherFunc(rpath, true)
return self.Apply(rpath, lpath, true)
}
When I run my test, I get (forgive me for omitting part of the real path to file):
too many arguments in call to self.Apply
have (string, string, bool)
want (string, string)
../remotesystem.go:178: (*RemoteSystem).Apply redeclared in this block
previous declaration at ../remotesystem.go:185
Overloading isn't available in Go. Instead of writing functions with the same name that do different things, it is preferable to be more expressive with what the function does in the function name. In this instance, what would commonly be done is something like this:
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
func (self *RemoteSystem) ApplyDynamic(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
return self.Apply(rpath, lpath, true)
}
Just by the name of the function, you can easily tell what is different and why.
Another example to provide some context (pun intended).
I write a lot of Google App Engine code in Go using go-endpoints. The way to log things is different depending on if you have a context or not. My logging functions ended up like this.
func LogViaContext(c context.Context, m string, v ...interface{}) {
if c != nil {
appenginelog.Debugf(c, m, v...)
}
}
func LogViaRequest(r *http.Request, m string, v ...interface{}) {
if r != nil {
c := appengine.NewContext(r)
LogViaContext(c, m, v...)
}
}
From the Reddit post:
Unicode. I can tell by the pixels.
Go doesn't support function overloading. But it does support using Unicode characters in function names, which allows you to write function names that look like other function names.
The first one is setValue, the second one is setV\u0430lue aka setV\xd0\xb0lue (with CYRILLIC SMALL LETTER A) and the third is setVal\U0001d69ee aka setVal\xf0\x9d\x9a\x9ee (with MATHEMATICAL MONOSPACE SMALL U).
See also:
Does the Go language have function/method overloading? (stackoverflow.com)
Why does Go not support overloading of methods and operators? (golang.org)
Alternative for function overloading in Go? (stackoverflow.com)
package main
import (
......
"fmt"
......
)
func main() {
......
xxx:=new(xxx)
fmt.Println("1")
......
xxx.Println()//confusing
}
type xxx struct{
one int
two string
}
func (yyy *xxx) Println(){
fmt.Println("2")
yyy.Print(3)//confusing too
}
func (this *xxx) Print(a int){
fmt.Println(a)
}
This question is hunted me,what is the fastest way to tell whether it is a package name or an object name,as the code presented above,in the main func,fmt is known as a package name,because everybody knows.But when comes to xxx.Println(),how would you know whether it's a package name or an object name,assuming that the main function contains many lines of code,and it is hard to pin point the declaration of object "xxx",and,there are many packages imported and it is hard for you to search for every line of import() to see if "xxx" is listed in the packages,how do you tell what xxx is?
Same as func Println,you just come straight forward to yyy.Print(3),the receiver in the func declaration is hard to find because it is out of the screen,how would you tell what yyy is the fastest way,yyy could be either the package name and the receiver name.
If there is no such an easier way,does that mean I should always search for the import() listed packages first,and scroll the screen to the very beginning of the func declaration to find what is the receiver name,and then I can know what it is?That sounds to take too much time!
For the second question (yyy.Println() inside method Println()), I think it’s standard Go style to name your receivers with very short names. So, standard Go style would suggest:
func (x *xxx) Println() {
fmt.Println(2)
x.Print(3)
}
As for the first question… I’m not sure if you’re talking about your code, or somebody else’s code. I would say it’s pretty standard that you eventually learn about what modules a given program or library is using. (Really short variable names, and then camelCase variable names also help.)
Using short-term memory, quickly scan the source code for salient features.
package main
import (
// ......
"fmt"
// ......
)
type xxx struct {
one int
two string
}
func (this *xxx) Print(a int) {
fmt.Println(a)
}
func (yyy *xxx) Println() {
fmt.Println("2")
yyy.Print(3) // yyy is receiver *xxx
}
func main() {
// ......
xxx := new(xxx)
fmt.Println("1")
// ......
xxx.Println() // xxx is var xxx
}
Apply the language rules. For example, block and scope rules.
With practice, it's easy.
References:
The Go Programming Language Specification
Import declarations
Qualified identifiers
Selectors
Blocks
Declarations and scope
I've recently learnt that in the net/http package, there's a pattern of usage that keeps confusing me most. It is function type conversion. It is like this:
(function a) ->convert to-> (type t)
(type t) ->implentments-> (interface i)
So, if there's a function that takes interface i as its parameter, it will invoke the function a, this is the way net/http implements it.
But when I write my own code, I've had many misunderstandings on this pattern. My code goes like this:
package main
import (
"fmt"
)
type eat interface {
eat()
}
type aaa func()
func (op *aaa) eat() {//pointer receiver not right
fmt.Println("dog eat feels good")
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func feelsGood(a eat) {
a.eat()
}
func main() {
b := aaa(dog)
feelsGood(b)
}
//error:aaa does not implement eat (eat method has pointer receiver)
Type aaa has method eat, the same function name and parameter signature, which conforms to the rule of interface eat, but why does it give that error? Does the receiver matter?
Another question is with only a function and type, excluding an interface, the code goes like this:
package main
import (
"fmt"
)
type aaa func()
func (op *aaa) eat() {
op()
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func main() {
obj:=aaa(dog)
obj.eat()
}
//error:cannot call non-function op (type *aaa)
First, is op an anonymous function, regardless of the error?
Second, it works well after I remove the asterisk, but why? op is instance of type aaa, receiver is op, does op stand for function dog()? The http package uses f(w,r) the same way, but it is a little bit of hard to understand. Is op a type, or an instance, or an anonymous function?
It seems like my comprehension of function converting is not right, but I've also checked many posts on Google, and none of them can teach me how to think of it and use it correctly.Thank you!
Question 1:
In Go, for a type T (like aaa in your case), T and *T have different method sets.
So, a value of type T can only access method:
func(t T)Foo() { ... }
While a value of type *T can access both methods:
func(t T)Foo() { ... }
func(t *T)Bar() { ... }
In your case, you have two options. Either you declare the eat method for aaa instead od *aaa:
func (op aaa) eat() {
op()
}
Or you pass the pointer to b to feelsGood:
feelsGood(&b)
Question 2:
Yes, this question is related to the first. But in this case you can access the method because obj.eat() will be short for (&obj).eat().
Your problem here is that you cannot call a function on the function pointer (op *aaa). Your options are to either create the method for aaa instead of *aaa:
func (op aaa) eat() {
op()
}
Or to call the op function on the value and not the pointer:
func (op *aaa) eat() {
(*op)()
}
For the first part of your question: See http://golang.org/doc/faq#different_method_sets which exmplains everything better than I could. You may even search stackoverflow and the golang-nuts mailing list for this question as this comes up very often.
The second is just the same IMHO: aaa doesn't have an eat-method (only *aaa has).
Is there a technical reason why unexported fields are not included by encoding/json? If not and it is an arbitrary decision could there be an additional back door option (say '+') to include even though unexported?
Requiring client code to export to get this functionality feels unfortunate, especially if lower case is providing encapsulation or the decision to marshal structures comes much later than design of them.
How are people dealing with this? Just export everything?
Also, doesn't exporting field names make it difficult to follow suggested idioms. I think if a struct X has field Y, you can not have an accessor method Y(). If you want to provide interface access to Y you have to come up with a new name for the getter and no matter what you'll get something un-idiomatic according to http://golang.org/doc/effective_go.html#Getters
There is a technical reason. The json library does not have the power to view fields using reflect unless they are exported. A package can only view the unexported fields of types within its own package
In order to deal with your problem, what you can do is make an unexported type with exported fields. Json will unmarshal into an unexported type if passed to it without a problem but it would not show up in the API docs. You can then make an exported type that embeds the unexported type. This exported type would then need methods to implement the json.Marshaler and json.Unmarshaler interfaces.
Note: all code is untested and may not even compile.
type jsonData struct {
Field1 string
Field2 string
}
type JsonData struct {
jsonData
}
// Implement json.Unmarshaller
func (d *JsonData) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &d.jsonData)
}
// Getter
func (d *JsonData) Field1() string {
return d.jsonData.Field1
}
Stephen's answer is complete. As an aside, if all you really want is lowercase keys in your json, you can manually specify the key name as follows:
type Whatever struct {
SomeField int `json:"some_field"`
}
In that way, marshaling a Whatever produces the key "some_field" for the field SomeField (instead of having "SomeField" in your json).
If you're dead-set on keeping unexported fields, you can also implement the json.Marshaler interface by defining a method with the signature MarshalJSON() ([]byte, error). One way to do this is to use a struct literal that simply has exported versions of the unexported fields, like this:
type Whatever struct {
someField int
}
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(struct{
SomeField int `json:"some_field"`
}{
SomeField: w.someField,
})
}
That can be a bit cumbersome, so you can also use a map[string]interface{} if you prefer:
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"some_field": w.SomeField,
})
}
However it should be noted that marshaling interface{} has some caveats and can do things like marshal uint64 to a float, causing a loss of precision. (all code untested)