Does Go have Partial Classes? - go

Are there partial classes in Go?
Like the one here in C#?
http://msdn.microsoft.com/en-us/library/wa80x488.aspx
I suppose there isn't any as you cannot partially declare structs.

The method declarations for a type do not need to be in the same source file as the type declaration or other method declarations for the type. The method declarations do need to be in the same package as the type declaration.
A type declaration cannot be split across files.
Go does not have classes.

In Go you can have a method associated with any type within the same package in any file. Take this small example of object foo with function Bar.
package main
import "fmt"
type foo struct {} // put variables associated with the type here
func ( /*f*/ foo) Bar() { // put a value in front of foo if u need to access any elements in the object
// do something interesting
fmt.Println("Method called :D")
}
func main() {
example := foo{}
example.Bar()
}
As long as foo and bar declarations occur in the same package they can be placed in any file.
I hope this demonstrated the desired functionality you are trying to implement / wondering if Go can support.

Related

How to hide the default type constructor in golang?

The reason I have this question is that I often make mistakes that I forgot to specify a value to a struct's field, then the compiler is fine, but the zero value causes bugs.
Here is an example. Say I have a type Foo defined like this in a package:
package types
type Foo struct {
RequiredField1 string
RequiredField2 string
}
It is exposed and has 2 fields that I'd like both of them to be specified when the Foo struct is created.
Then I can import and use it in my main function like this:
package main
import (
"github.com/foo/bar/types"
)
func main() {
f := &Foo{
RequiredField1: "fff",
}
fmt.Printf("f.RequiredField2: %v", f.RequiredField2)
}
This causes a bug because I forgot to specify RequiredField2 which is required. And I often make this kind of bugs :p
Now, in order to leverage the compile and prevent this mistake, I made a constructor function for Foo and asks for the required values.
func NewFoo(field1 string, field2 string) *Foo {
return &Foo{Field1: field1, Field2: field2}
}
So that if I forgot to pass field2, the compiler won't compile my code:
func main() {
f := NewFoo("foo")
fmt.Printf("f.Field2: %v", f.Field2)
}
The build will fail:
./prog.go:18:13: not enough arguments in call to NewFoo
have (string)
want (string, string)
Now the question is: how to stop the foreign callers (callers from other namespaces) from calling the default constructor of Foo, that is &Foo, and force them to use the NewFoo?
If I can, then I'm safe since NewFoo is the only way to create the Foo type and the compiler helps me ensure all fields are present when calling it.
You can avoid this problem by making Foo type unexported.
You can make an interface that is Exported and has all the methods that Foo type performs.
Example:-
type Foo interface{
DoSomething()
}
type foo struct{
RequiredField1 string
RequiredField2 string
}
func NewFoo(requiredField1 string,requiredField2 string)*foo{
return &foo{
RequiredField1:requiredField1,
RequiredField2:requiredField2,
}
}
func (f *foo)DoSomething(){
// your implementation
}
In this way all the caller will be able to access it but cannot create foo without NewFoo function.
How to hide the default type constructor in golang?
You cannot for an exported type.
Get used to it, it is not a problem in real life.
(For unexported types, just provide a func NewUnexportedType(...) unexportedType. )
Effective Go
it's helpful to arrange when designing your data structures that the
zero value of each type can be used without further initialization.
we often need to change the type definition, like adding more fields
That is why you should make the zero value for struct fields significant. The behavior is by design. For example, it is used to maintain the Go 1 compatibility guarantee.

How to correctly import method from another package

I have the following simple project:
myapp/
|- mainlib/main.go
|- tables/sometable.go
In sometable.go I have:
package tables
import (
"fmt"
)
type TableName string
func (table TableName) GetDataFromDataSource() string {
return "getdatafromdatasource"
}
Those are methods, and now I want to use them in main.go:
package main
import t myapp/tables
type tableName t.TableName // and such "attempts"
I've tried:
t.GetDataFromDataSource()
t.tableName("string").GetDataFromDataSource()
tableName("string").GetDataFromDataSource()
and similar combinations and compiler says "undefined reference" still...
So, my question is: how to correctly use method from another package in such context? Of course my methods starts with captial letters and are exported. If I try to use simple function with same name (not method), then it works correctly...
This has nothing to do with packages, but with alias declaration vs type definition.
Let's take a simple example:
type A string
func (a A) Print() {
fmt.Println(a)
}
type B A
type C = A
func main() {
A("A").Print()
B("B").Print()
C("C").Print()
}
This fails to compile on line B("B").Print() with:
B("B").Print undefined (type B has no field or method Print)
The spec clearly spells out the difference in the type declarations section
The line type B A is a type definition:
A type definition creates a new, distinct type with the same
underlying type and operations as the given type, and binds an
identifier to it.
While the line type C = A is an alias declaration:
An alias declaration binds an identifier to the given type.
The former is a new type, so the receiver type A for method Print() will not match the type B.
The latter is just a name pointing to type A.
You'll want to change your code to the following, using type aliases:
import t myapp/tables
type tableName = t.TableName
tableName("string").GetDataFromDataSource()
And a few notes:
t.GetDataFromDataSource() can't work, it's a method and needs a receiver
t.tableName("string").GetDataFromDataSource() won't work, t.tableName is not a thing, or if it is, it's not exported
you can't talk about importing methods, only packages are imported. A method is either exported or not, but it's the package you import

golang interface that depends on interface

I am not sure if these should be two separate questions or one, but it seems to me as one question of two parts - How go interfaces are supposed to be used? I have this two struggles:
The methods of the interfaces are globally scoped: If I have interface A and interface B that both implement the same method Foo, but with different arguments or return types I am unable to implement both at the same time from the same type. For example, I have GetBytes() method in one interface having return type []byte and in another ([]byte, error) How I should overcome this issue?
Another issue I have is when I try to define interface say interface A that has a method that returns interface B that is defined in the same layer. Now if I want to create an object that implements A, if I return struct that implements B go is not smart enough to deduce that this method implements the method in A and it forces me to create dependency on B. This seems to completely defeat the point of the way interfaces work in go at first place. How can I avoid this issue?
for example, if I have:
type B interface {
Bar()
}
type A interface {
Foo() B
}
for the following structs :
type b_impl struct{}
func (b b_impl) Bar() {}
type a_impl struct{}
A foo method
func (a a_impl) Foo() b_impl {}
does not satisfy the interface A and I need to make it:
func (a a_impl) Foo() B {}
which makes a dependency to the package where B is declared.
1st question:
In go you need to make different function names, when you want to do different tasks. Let's look into the standard library at the strconv package how things are solved there: https://golang.org/pkg/strconv/#pkg-index
Look to the different declaration of the append function there. There are functions for every different type.
So if you expect a FooInt funtion your interface should be also a FooInter, ...
2nd question:As a small example. You don't need to import the whole io package, when you want to use the io.Writer interface. It is totaly ok to copy the Writer declaration into your own package. If you do that correct, every io.Writer implementation will automatically implement your own Writer interface.
After reading the other comments maybe you have a different situation:
Let's say there is a package a and b with the interface a.A and b.B. If there is the situation that:
type A interface{
Foo() b.B
}
and you have to write an implementation for a.A, then you need to import package b. But that makes your binaries not bigger, because you will always need to import package a, which depends on b.
For implementing an interface, you need to have exactly the same method name and signature. Means the signature must be with the same types.
As much as it seems weird, these two don't have the same signature:
Foo() B
Foo() b_impl {}
It doesn't matter that b_impl implements B.
To overcome the need to import the package B is declared in, you can use anonymous type. This way the compiler won't require a specific type for the method signature.
type A interface {
Foo() interface{Bar()}
}
Which also can be written as embedding B:
type A interface {
Foo() interface{B}
}
Still, a_impl must have same signature, so it also needs to return an anonymous interface. You can also declare the same B interface in the package of a_impl, and embed it in an anonymous interface.
package impl
type B interface {
Bar()
}
type b_impl struct{}
func (b b_impl) Bar() {}
type a_impl struct{}
func (a a_impl) Foo() interface{B} {
return b_impl{}
}
I don't know if it's a bad practice or not, probably there are cases which redesign is required instead of doing this.

Embedded struct

Is it possible to inherit methods of a type without using embedded structs?
The first snippet of code is working code that embeds the Property struct in Node and I'm able to call node.GetString that's a method on Properties. The thing I don't like about this is when I initialize Node I have(?) to initialize the Properties struct within it. Is there a way around this?
package main
import "fmt"
type Properties map[string]interface{}
func (p Properties) GetString(key string) string {
return p[key].(string)
}
type Nodes map[string]*Node
type Node struct {
*Properties
}
func main() {
allNodes := Nodes{"1": &Node{&Properties{"test": "foo"}}} // :'(
singleNode := allNodes["1"]
fmt.Println(singleNode.GetString("test"))
}
Ultimately, I would like to do something like the following. Where Node is of type Properties and initializing does not require initializing a Property struct too. The following code doesn't work but may be clear what my goal is.
package main
import "fmt"
type Properties map[string]interface{}
func (p Properties) GetString(key string) string {
return p[key].(string)
}
type Nodes map[string]*Node
type Node Properties
func main() {
allNodes := Nodes{"1": &Node{"test": "foo"}} // :)
singleNode := allNodes["1"]
fmt.Println(singleNode.GetString("test")) // :D
}
I'll be adding more structs that will use Properties's methods which is why I'm asking. If I only had Node, I would just have methods for Node and be done. But because I'll have more than Node I find it kind of redundant to add the same methods to all the structs that embed Properties
I guess more to the exact problem, I want to use Properties methods from Node without having to initialize Properties.
So you're running into an idiosyncrasy of Go here. Embedding is the only way in which methods of one struct can get "promoted" to appear to exist on another struct. While it feels intuitive that type Node Properties should expose the Properties methods on Node, that effect of that syntax is for Node to take on the memory layout of Properties but not any of its methods.
It doesn't explain why this design choice was made but the Go Spec is at least specific if dry. If you read it exactly as it appears, with no interpretation, it is very accurate:
The method set of an interface type is its interface. The method set of any other type T consists of all methods declared
with receiver type T
GetString has a receiver of type Properties not Node, seriously, interpret the spec like you're an accountant with no imagination. With that said:
Further rules apply to structs containing anonymous fields, as described in the section on struct types.
...
A field or method f of an anonymous field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.
Promoted fields act like ordinary fields of a struct except that they
cannot be used as field names in composite literals of the struct.
Given a struct type S and a type named T, promoted methods are
included in the method set of the struct as follows:
If S contains an anonymous field T, the method sets of S and *S both
include promoted methods with receiver T. The method set of *S also
includes promoted methods with receiver *T.
If S contains an anonymous
field *T, the method sets of S and *S both include promoted methods
with receiver T or *T.
That line about composite literals is this thing that forces you to declare Properties inside every Node you create.
p.s. Hi Jeff!
The short answer to your last question is simply No.
There is a big difference between type declaration and embedding in golang, you can make your last example working by manually make a type conversion between Node and Properties:
package main
import "fmt"
type Properties map[string]interface{}
func (p Properties) GetString(key string) string {
return p[key].(string)
}
type Nodes map[string]*Node
type Node Properties
func main() {
allNodes := Nodes{"1": &Node{"test": "foo"}} // :)
singleNode := allNodes["1"]
fmt.Println(Properties(*singleNode).GetString("test")) // :D
}
But it's clearly that is not what you want, you want a struct embedding with a syntax of type aliasing, which is not possible in golang, I think that you should stuck with the your first approach and ignore the the fact the code is redundant and ugly .

How do I properly structure a package with sub packages in Go where a single type will be the receiver on most of the methods?

I'm currently in the design stage of writing a utility library that will make interaction with the x-go-binding a bit easier. (I've done this before with Python and xpyb.) For example, it will help with querying information defined in the EWMH spec and binding keys to callback functions. (And much more.) So as my initial idea for a package layout, consider:
xutil
ewmh
keybind
Where each is its own package. (Similar to how the standard library's image package is setup.)
What's unique about my situation is that almost every x-go-binding call requires some combination of an xgb connection object or a root window identifier. Therefore, it makes sense to me to store this information in a struct like so:
type XUtilConnection struct {
conn xgb.Conn
root xgb.Id
// a few other things, like a mapping of events to callbacks
}
So that I'd have a factory that could be used like so:
xconn = xutil.NewXUtilConnection(blah blah)
And it could be used like:
xconn.get_active_window()
xconn.bind_key("Shift-a", my_callback_fun)
There may also be functions like:
keybind.get_keycode("a")
ewmh.get_atom("_NET_ACTIVE_WINDOW")
My problem of course is that receivers, to my knowledge, can only be of types that have been declared in the same package. If I separate my packages, I cannot use my XUtilConnection type as a receiver in any of my sub-packages.
I suspect that my answer is going to be making this one big package separated into different logical files, but I fear that this might lead to namespace clutter. (For example, implementing the EWMH spec is probably on the order of 100+ functions.)
I am also aware that I could define a new container type in each sub-package for my XUtilConnection object. (I've heard that this should be a struct containing a single member XUtilConnection to avoid casting.) But this seems like a really messy situation to me, and would prevent the kind of semantics I'd like. (i.e., using an XUtilConnection struct to call methods in several different modules.)
I would suggest to use embedding.
In package xutil:
type XUtilConnection struct {
*ewmh.EWMH // Embed all methods of *ewmh.EWMH
*keybind.KeyBind // Embed all methods of *keybind.KeyBind
}
In package xutil/ewmh:
type EWMH struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some EWMH methods:
func (e *EWMH) GetAtom(name string) { ... }
func (e *EWMH) ...
In package xutil/keybind:
type KeyBind struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some keybind methods:
func (k *KeyBind) GetKeyCode(s string) { ... }
func (k *KeyBind) ...
This will enable you to directly call EWMH's and KeyBind's methods on values of type *XUtilConnection:
var c *XUtilConnection = ...
c.GetAtom("_NET_ACTIVE_WINDOW") // Call (*emwh.EWMH).GetAtom(string)
c.GetKeyCode("a") // Call (*keybind.KeyBind).GetKeyCode(string)
I'm not sure if I understood correctly the problem (I'm confused by seeing package names where they seem to be discussed as method receivers?), but I guess passing around an interface instead of the [*]struct would enable satisfying it from within any package. One can also always do something like (totally untested code):
package foo
type Foo interface { Bar(); Baz() }
----
package qux
import "foo"
type qux struct { foo.Foo; myStuff t }
func Foo(f foo.Foo) foo.Foo {
return qux{f, &t{}}
}
func (q qux) Bar() {
// smthg
}
To e.g. "override" f.Bar in package qux and "inherit" f.Baz() unaltered.

Resources