field in interface[golang]? - go

is there any solution to force struct have specific property(defined in interface)?
or define a property(attribute,field) in interface?.
as i see interface is always accept method not property?. (https://gobyexample.com/interfaces)
type geo interface {
PrintType()
typ string//not function , but field
}
type circle struct {
typ string
}
func (c circle) PrintType() {
fmt.Println(c.typ)
}
thanks

Interfaces are about methods only, not properties, because interfaces are about behavior. So there is no way to force a struct to have something. Rather the preferred method is to have an accessor to that member.

Related

Golang: How to embed interface with different type parameters?

The code gives me error: DB redeclared.
Is there any idiomatic way to solve it? Or any work-around?
TIA
type a struct {
DB[int64]
DB[string]
}
type b interface {
DB[int64]
DB[string]
}
type DB[T any] interface {
GetList(query string) ([]T, error)
}
You can't embed the same interface, even with different type parameters. Regardless of how it is instantiated, you are trying to promote into the b interface two methods with the same name GetList and different signatures — given by the different instantiations of DB.
The situation is similar, although not technically the same, for embedding into a struct. In structs, the name of the embedded field is the name of the type — DB —, and a struct can't have two non-blank fields with the same name.
About how to solve this issue, it depends what you want to accomplish.
If you want to convey that "a implements DB with either type parameter" you can embed DB[T] and make a itself generic, and restrict a's type parameters:
type a[T int64 | string] struct {
DB[T]
}
// illustrative implementation of the DB[T] interface
// if you embed DB[T] you likely won't use `a` itself as receiver
func (r *a[T]) GetList(query string) ([]T, error) {
// also generic method
}
This is okay because DB's type parameter is constrained to any, and a's type parameter is more restrictive. This allows you to use a in other generic methods, or choose a specific type upon instantiation, but the implementation of GetList has to be parametrized too.
Otherwise if you need a to have separated methods that return int64 or string, you must give it different names.
Finally, you can embed instances of DB into two interfaces with different names, and then embed those into a instead.
type a struct {
DBStr
DBInt
}
type DBStr interface {
DB[string]
}
type DBInt interface {
DB[int64]
}
This way though the top-level selector isn't available because the method names are still the same. The program compiles, but you'll have to explicitly choose which field to call the method on:
myA := a{ /* init the two fields */ }
res, err = myA.DBStr.GetList(query)
// res is type []string
// or
res, err = myA.DBInt.GetList(query)
// res is type []int64

how to write a function to process two types of input data in golang

I have multiple structs share some fields. For example,
type A struct {
Color string
Mass float
// ... other properties
}
type B struct {
Color string
Mass float
// ... other properties
}
I also have a function that only deals with the shared fields, say
func f(x){
x.Color
x.Mass
}
How to deal with such situations? I know we can turn the color and mass into functions, then we can use interface and pass that interface to the function f. But what if the types of A and B cannot be changed. Do I have to define two functions with essentially the same implementation?
In Go you don't the traditional polymorphism like in Java, c#, etc. Most things are done using composition and type embedding. A way of doing this simply is by changing your design and group the common field in a separate struct. It's just a different of thinking.
type Common struct {
Color string
Mass float32
}
type A struct {
Common
// ... other properties
}
type B struct {
Common
// ... other properties
}
func f(x Common){
print(x.Color)
print(x.Mass)
}
//example calls
func main() {
f(Common{})
f(A{}.Common)
f(B{}.Common)
}
There are other ways too by using interfaces and getters mentioned here but IMO this is the simplest way

How GoLang's typecast to interface implemented by a struct and embedded struct works

I recently came across a code that is doing something I don't understand.
There are multiple structs having the same embedded struct and an interface that defines methods returning pointer to each struct. This interface is implemented by the embedded struct but only 'partially' by the individual structs, as such, each struct only implements the method where the pointer to that struct is returned.
For better understanding, here is the representative code:
type BarStocks interface {
GetVodka() *Vodka
GetMartini() *Martini
GetBourbon() *Bourbon
GetNegroni() *Negroni
GetManhattan() *Manhattan
}
type BaseAttributes struct {
ID uuid.UUID
Quantity float64
CreatedAt time.Time
UpdatedAt time.Time
}
func (e *BaseAttributes) GetVodka() *Vodka {
return nil
}
func (e *BaseAttributes) GetMartini() *Martini {
return nil
}
func (e *BaseAttributes) GetBourbon() *Bourbon {
return nil
}
func (e *BaseAttributes) GetNegroni() *Negroni {
return nil
}
func (e *BaseAttributes) GetManhattan() *Manhattan {
return nil
}
And then each individual struct implements only the method where its pointer is returned, for example:
type Vodka struct {
BaseAttributes
Label string
}
func (v *Vodka) GetVodka() *Vodka {
return v
}
Now in the code, this setup is used to typecast the individual struct to the interface as a pointer, something like this:
func someFunc() BarStocks {
v := Vodka{}
return &v
}
Now I am not too deep into Go yet and so unable to comprehend how the pointer to the struct becomes the same type as the interface.
Thanks in advance for any insight into this.
I'll do my best to answer the question I think you're asking.
The documentation on embedding explains the behavior you're seeing,
There's an important way in which embedding differs from subclassing.
When we embed a type, the methods of that type become methods of the
outer type, but when they are invoked the receiver of the method is
the inner type, not the outer one.
This explains how a Vodka struct, which embeds struct BaseAttributes which implements all of the methods in BarStocks is able to satisfy the interface Barstocks. This excerpt, however, does not explain how we effectively override GetVodka() for our Vodka struct.
To understand this we need to read another excerpt from the documentation.
Embedding types introduces the problem of name conflicts but the rules
to resolve them are simple. First, a field or method X hides any other
item X in a more deeply nested part of the type.
This excerpt explains that If Vodka implements GetVodka() and embeds a struct (BaseAttributes) which also implements GetVodka(), the outer-most definition is the one that takes precedence.
The combination of these behaviors explain how Vodka satisfies the BarStocks interface and has the behavior you see in the example code.
The additional methods missing from Vodka, but present on BarStocks are implemented for BaseAttributes and if the method is missing from Vodka, the method from the embedded strut will be called instead.
Note, methods in an embedded struct will not have access to the parent struct members. Also note, if you wanted to call the embedded struct's method when it has been defined in the parent (as GetVodka is for Vodka) then you would prepend the embedded type's name to the method. For example
myDrink := someFunc()
myDrink.BaseAttributes.GetVodka()
This is obviously not helpful in this case as all of the BaseAttribute methods return nil, but may be helpful in the future.

Inheritance and interfaces

I want to express the extends behavior many languages possess.
In my Go Code I have a few structs that look like so:
type Base struct {
// Some fields
}
type BaseExtender struct {
Base
// Unique fields
}
type AnotherBaseExtender struct {
Base
// Unique fields
}
Now, I want to write a function that takes any Base since I only need it's "similar fields".
func UseTheBase(b Base) {
testVal := b.thingICareAbout
}
However, this doesn't work. I've done some digging into interface and thought I could do something like:
type Base interface {
// Some fields
}
Except it appears that Go automatically infers interfaces by method implementation. Is there a way to mimic this behavior so I can pass any Base into my function, and not have to implement some nop method on the Base struct and all of it's extenders?
Thanks!
Base implies you want inheritance in Go, Go deliberately eschews inheritance, don't try to recreate it. You can embed types but think of this as embedding behaviour, not just data (as you might be tempted to in an inheriting language).
You're on the right lines with your solution but need public methods and yes interfaces are defined in terms of methods. Just define the interface where you call it as:
type Doer interface {
DoSomething()
}
...
func doit(d Doer) {
d.DoSomething()
}
doit doesn't care what its argument is as long as it has a DoSomething method. Obviously this is a trivial example and there's no point in it, but if you need to override something in all extenders, ask yourself why Base exists, if it is just to add some fields, that's probably not enough reason for a separate type, just add the fields where you need them.
Try to avoid the vast taxonomies of types that you might construct in other languages.
To add on, a common pattern I use is:
type Base interface {
SomeFunction() int
}
type SimpleBaseImpl struct {
// Unique fields
}
func (s SimpleBaseImpl) SomeFunction() int {
return 0
}
type SomethingMoreComplicated struct {
SimpleBaseImpl
// Unique fields
}
Then you could treat SomethingMoreComplicated as "type" Base – but again, its important to note the golang preference for composition (shown here) over inheritance.

Private embedded struct when importing a struct from another package

I have a project which relies on a struct imported from another package, which I will call TheirEntity.
In the example below, I (ahem) embed TheirEntity in MyEntity, which is an extension of TheirEntity, with added functionality.
However, I don't want to export TheirEntity in the MyEntity structure, as I would rather the consumer not access TheirEntity directly.
I know that Go embedding is not the same as inheritance in classical OOP, so maybe this is not the correct approach, but is it possible to specify embedded structs as "private", even if they are imported from another package? How might one achieve the same thing in a more idiomatic fashion?
// TheirEntity contains functionality I would like to use...
type TheirEntity struct {
name string
}
func (t TheirEntity) PrintName() {
fmt.Println(t.name)
}
func NewTheirEntity(name string) *TheirEntity {
return &TheirEntity{name: name}
}
// ... by embedding in MyEntity
type MyEntity struct {
*TheirEntity // However, I don't want to expose
// TheirEntity directly. How to embed this
// without exporting and not changing this
// to a named field?
color string
}
func (m MyEntity) PrintFavoriteColor() {
fmt.Println(m.color)
}
func NewMyEntity(name string, color string) *MyEntity {
return &MyEntity{
TheirEntity: NewTheirEntity(name),
color: color,
}
}
Since the question was asked, Go saw the addition of type aliases to the language with the 1.9 release in 2017. It turns out that, through an unconventional use of type aliases, you can have your cake and eat it too!
First, declare an unexported alias for the third-party type you wish to embed in your struct:
type theirEntity = TheirEntity
Then, simply embed that alias instead of the original type:
type MyEntity struct {
*theirEntity
color string
}
(Playground)
[I]s it possible to specify embedded structs as "private", even if they are imported from another package?
No.
How might one achieve the same thing in a more idiomatic fashion?
By not-embedding but making it a unexported named field.
Like this:
type MyEntity struct {
*privateTheirEntity
}
type privateTheirEntity struct {
*TheirEntity
}

Resources