Go "this"-keyword - go

After diving into the docs I couldn't find the answer to my following question:
Is there any reason against using this for referring to the current object as in the following example?
type MyStruct struct {
someField string
}
func (this MyStruct) getSomeField() string {
return this.someField
}

There is no technical reason not to do this.
It does go against the general guidelines as explained here:
Don't use generic names such as "me", "this" or "self", identifiers typical of object-oriented languages that place more emphasis on methods as opposed to functions.
I would also like to add that in languages that use this (or self), this is always a pointer. For method receivers in Go, this is not necessarily the case.

Related

Polymorphism on structs without methods in Go

I'm working on several web server projects in Go, and there is a common problem that I'm always facing. I know we can achieve something like polymorphism in Go with interfaces and methods, but many times I had a scenario that I needed polymorphism on some data-holder structs that (maybe) just had some common fields, and no methods at all.
For example consider a story writing platform, where each user can write short stories and novels:
type ShortStory struct {
Name string
ID int
Body string
}
type LongStory struct {
Name string
ID int
Chapters []string
}
Now I simply want to have a data layer function, say GetStories(), which fetches all stories written by a user from database.
func GetStories(id int) []SOME_TYPE {
...
}
There are really no methods that I want to have on my ShortStory and LongStory structs. I know I can add a dummy method and let them satisfy some Storier interface, then use that interface as return type. But since there is no method I would want on a data container model, adding a dummy method just for the language to enable a feature, seems like a poor design choice to me.
I can also make the function return []interface{}, but that's against the whole idea of "typed language" I believe.
Another way is to have two separate GetShortStories() and GetLongStories() methods, which return a slice of their own type. But at some point I would finally want to merge those two slices into one and there I would again need a []interface{}. Yes, I can return a JSON like:
{
"short_stories" : [...],
"long_stories" : [...]
}
But I want my json to be like:
[{...}, {...}, {...}]
And I wouldn't change my APIs because of a language's limits!
I'm not a pro in Go, so am I missing something here? Is there a Go-ish approach to this, or is it really bad language design on Golang's side?
If you cannot express what you want to do using the features of a language, you should first try to change the way you structure your program before blaming the language itself. There are concepts that cannot be expressed in Go but can be expressed well in other languages, and there are concepts you cannot express well in other languages but you can in Go. Change the way you solve the problem to effectively use the language.
One way you can address your problem is using a different type of struct:
type Story struct {
Name string
ID int
ShortBody string
Chapters []string
}
If the Chapters is empty, then it is a short story.
Another way:
type Story struct {
Name string
ID int
Content StoryContent
}
type StoryContent interface {
Type() string
}
type ShortStory interface {
StoryContent
Body() string
}
type LongStory interface {
StoryContent
Chapters() []string
}
etc.

Enums in GraphCool? How to use them? No Documentation

GraphCool doesn't have much documentation on Enums, so I am just posting my Enum info for those who could use it:
Enums are arguments of an object that can only have specified values. GraphCool also, to my knowledge, requires them to be defined with a default value.
An example Enum is (write them in the enums tab):
enum PublishersEnum {
PEARSON
WILEY
MCGRAWHILL
}
An example type with enum:
type Book {
...
publisher: PublishersEnum #defaultValue(value: PEARSON)
...
}
Recommendations/conventions:
Use all caps to help distinguish enum usage.
Name the enum with "Enum" in the name somewhere
Concerns:
I have not had good luck with the graph cool interface, when I try to migrate from a string to an enum, the migration value and such didn't work well, hopefully others will have better luck.

Use map[string]SpecificType with method of map[string]SomeInterface into

I get cannot use map[string]MyType literal (type map[string]MyType) as type map[string]IterableWithID in argument to MapToList with the code below, how do I pass in a concrete map type to method that expects a interface type?
https://play.golang.org/p/G7VzMwrRRw
Go's interface convention doesn't quite work the same way as in, say, Java (and the designers apparently didn't like the idea of getters and setters very much :-/ ). So you've got two core problems:
A map[string]Foo is not the same as a map[string]Bar, even if Bar implements Foo, so you have to break it out a bit (use make() beforehand, then assign in a single assignment).
Interface methods are called by value with no pointers, so you really need to do foo = foo.Method(bar) in your callers or get really pointer-happy to implement something like this.
What you can do to more-or-less simulate what you want:
type IterableWithID interface {
SetID(id string) IterableWithID // use as foo = foo.SetID(bar)
}
func (t MyType) SetID(id string) IterableWithID {
t.ID = id
return t
}
...and to deal with the typing problem
t := make(map[string]IterableWithID)
t["foo"] = MyType{}
MapToList(t) // This is a map[string]IterableWithID, so compiler's happy.
...and finally...
value = value.SetID(key) // We set back the copy of the value we mutated
The final value= deals with the fact that the method gets a fresh copy of the value object, so the original would be untouched by your method (the change would simply vanish).
Updated code on the Go Playground
...but it's not particularly idiomatic Go--they really want you to just reference struct members rather than use Java-style mutators in interfaces (though TBH I'm not so keen on that little detail--mutators are supes handy to do validation).
You can't do what you want to do because the two map types are different. It doesn't matter that the element type of one is a type that implements the interface which is the element type of the other. The map type that you pass into the function has to be map[string]IterableWithID. You could create a map of that type, assign values of type MyType to the map, and pass that to the function.
See https://play.golang.org/p/NfsTlunHkW
Also, you probably don't want to be returning a pointer to a slice in MapToList. Just return the slice itself. A slice contains a reference to the underlying array.

how to pass different types to a function

I have two golang functions, doing exactly same thing, one takes input a slice and the other takes a map as input. I want to combine this into one function, to avoid duplication.
func DoSomething([]data) {
//do something.
}
func DoSomething(map[string]data) {
//do something.
}
Combined function may look like:
func DoSomethingNew (param type) {
//param could be map or slice
}
I want to know if it is possible to pass different types to same function in golang and how. I googled but couldn't find anything relevant.
You can use interfaces Go Playground
func F(data interface{}) {
switch data.(type){
case []int:
fmt.Println("Slice")
fmt.Println(data)
case map[string]int:
fmt.Println("Map")
fmt.Println(data)
}
fmt.Println()
}
where you actually check for the type and do something based on the type.
There are several ways you could do this, but the simple way would be to make it so DoSomethingNew accepts the interface{} type. Inside of the method you would then do a type switch or in this case with only two options, perhaps just one type assertion, followed by the other, returning error if both fail. Another option would be to have both as arguments and check for nil inside the function with a similar if, else-if, else pattern to handle the error if the input is of neither types you're looking for. To make your code more safe you could move to a more strict interface than the empty one which all types implement. You could also do some method chaining or even implement the method with using the types themselves as the receiving type. Here's an example that shows a few of the ideas; https://play.golang.org/p/_v2AyFjGzv

Go Functions/Methods without a name

I'm really struggling to find a name for a type of function I've come across.
Here is the function in question:
https://github.com/go-fsnotify/fsnotify/blob/master/fsnotify.go#L32
This is how I'm using it (as per the fsnotify example):
select {
case event := <-watcher.Events:
log.Println("Event Triggered: ", event)
In that Println 'event' is returning the formatted string as per the function above, I'm just struggling to understand how a straight call to 'event' is using that function yet I would be expecting it to be accessed like the struct fields (event.Name, event.Op):
event.funcForReturningNicelyFormattedEvent()
It feels like this is a 'default' function as it has no name and it just returns the formatted data - I'm struggling to come up with the name/type/search term so I can find out more and understand the concept and importantly the reasoning behind it better.
Any help is appreciated.
It's very simple - println uses the String() method on any struct that implements it automatically. This is a classic use case of Go's implicit interfaces: every struct that has the methods an interface includes, is considered to be implementing the interface.
If it has func String() string it is considered a Stringer and used by fmt. You can use it on your own structs too, of course.
Function Println checks if the passed value implements interface Stringer. If it does it calls method String on this value. Event type implements that interface by supplying its implementation of String method in the excerpt you linked to.
In Go you don't have to declare that you implement interface.

Resources