I want to extend a struct definition from that of the other
type A struct {
name string
}
type B struct {
A
}
So here A is a sub struct of B. But I do not want that. Instead I want the B's definition to be the same as A without any nesting
var a A
var b B
fmt.Printf("%v, %v \t", a, b)
a.name = "john"
b.name = "rick"
fmt.Printf("%v, %v \t", a, b)
So output of this is {john} {{rick}}. I want it to be {john}{rick}
You can do:
type B A
However, if you do this, any methods you defined for A will not be available for B.
Related
If I have a struct type A which is used as a pointer (has pointer receivers only, the constructor returns *A, etc.), what is the difference between embedding a struct type B as B versus *B?
That is, what is the difference between
type B struct {...}
type A struct {
B
// ...
}
and
type B struct {...}
type A struct {
*B
// ...
}
For example, is there ever copying of the embedded field?
Edit: I should also mention that the embedded struct B only has pointer receivers.
The zero values of the two structures are different, which can be a significant ergonomic difference.
Consider an embedded type
type B struct {
X int
}
func (b *B) Print() { fmt.Printf("%d\n", b.X) }
If we embed this directly as an object
type AObj struct {
B
}
then the zero value of type AObj includes an embedded object of type B, which also has its zero value, and therefore we can safely
var aObj AObj
aObj.Print() // prints 0
But if we instead embed a pointer
type APtr struct {
*B
}
the zero value of this struct has a nil pointer value, and we can't really use it directly.
var aPtr APtr
aPtr.Print() // panics
Objects get copied in hopefully the way you might expect. If you create a new AObj object, it gets a copy of the embedded B.
aObj2 := aObj
aObj.X = 1
aObj2.Print() // prints 0, because it has a copy
If you create a new APtr object, it gets a copy of the *B, which means it shares the underlying concrete object.
aPtr.B = &B{}
aPtr2 := aPtr
aPtr.X = 1
aPtr2.Print() // prints 1, because both objects point at the same B
Runnable example at https://play.golang.org/p/XmOgegwVFeE
Consider a simple example program. A structAPtr embeds a pointer, a structAVal embeds a struct structB directly:
package main
import "fmt"
type structB struct {
foo int
}
type structAPtr struct {
bar *structB
}
type structAVal struct {
bar structB
}
func main() {
// referencing bStruct
b1 := structB{foo: 12}
aPtr := structAPtr{bar: &b1}
fmt.Println("Before assignment:")
fmt.Printf("aPtr.bar.foo = %d, b.foo = %d\n", aPtr.bar.foo, b1.foo)
aPtr.bar.foo = 42
fmt.Println("After assignment:")
fmt.Printf("aPtr.bar.foo = %d, b.foo = %d\n", aPtr.bar.foo, b1.foo)
// copying bStruct
b2 := structB{foo: 12}
aVal := structAVal{bar: b2}
fmt.Println("Before assignment:")
fmt.Printf("aVal.bar.foo = %d, b.foo = %d\n", aVal.bar.foo, b2.foo)
aVal.bar.foo = 42
fmt.Println("After assignment:")
fmt.Printf("aVal.bar.foo = %d, b.foo = %d\n", aVal.bar.foo, b2.foo)
}
The int structB.foo is used to demonstrate whether structB changes when manipulated inside of structAPtr or structAVal.
This program outputs:
Before assignment:
aPtr.bar.foo = 12, b.foo = 12
After assignment:
aPtr.bar.foo = 42, b.foo = 42 <------------ both changed
Before assignment:
aVal.bar.foo = 12, b.foo = 12
After assignment:
aVal.bar.foo = 42, b.foo = 12 <------------ only assignee changed
Looking at the result shows:
changing the value of the pointer to structB changes structB
changing the value of the copied version structB in structAVal leaves structB unaffected (it is still 5, even after 42 was assigned to aVal)
Edit:
If your structB has only pointer receivers anyways, the intended behavior is probably such that changing structB in strucA updated both of them. That's scenario 1 in my example and requires a pointer for sure. From A Tour of Go:
Methods with pointer receivers can modify the value to which the receiver points [...]. Since methods often need to modify their receiver, pointer receivers are more common than value receivers.
Hope that helps!
I have a struct B which inherits from the struct A. I have another struct C (which contains a slice of structs A) and I want to append B to C.
package main
type A struct {
target string
}
type B struct{
A
values []int
}
type C struct{
Cols []*A
}
func main() {
var values = []int{1,2,3}
var col1 = C{}
var col2 = &B {
A: A{
target: "txt",
},
values: values,
}
col1.Cols = append(col1.Cols, col2)
}
When running this code, it generates an error: cannot use col2 (type *B) as type *A in append
What's wrong please ? I'm newer
Ps: sorry for my bad English
col1.Cols is type *A, col2 is type *B, col2.A is type A, if you want to add new element to the slices, they should be of the same type.
so if you change the last statement to
col1.Cols = append(col1.Cols, &col2.A)
it will work.
I am little consfused about value type struct wrapped by pointer type struct.
Example:
package main
import (
"fmt"
)
type A struct {
id int
B
}
func (a *A) setId(val int) {
a.id = val
}
type B struct {
name string
}
func (b B) setNameViaValue(val string) {
b.name = val
}
func (b *B) setNameViaPointer(val string) {
b.name = val
}
func main() {
a := new(A)
a.setId(1)
a.setNameViaValue("valuename")
fmt.Println(a)
a.setNameViaPointer("pointername")
fmt.Println(a)
}
I would expect that referencing through pointer type A struct(which addresses concrete memory) that wraps B value type struct will set inner value no matter what kind of refence to B is used (B/*B). This is also related to type definition. Can anyone also explain what is different when I define it like this? Is there any usecase scenario?
type A struct {
id int
*B
}
Why doesn't setNameViaValue end up setting the name
If you declare a method with a value (non-pointer) receiver, then that method cannot "modify" the receiver cause it will actually receive a copy.
That's why the "name" is not set as you expected with the setNameViaValue method.
If you want to be able to set the name of B in that way, only setNameViaPointer is an option.
You can read more about the differences between method and value receivers here:
https://tour.golang.org/methods/8
Why can you actually invoke the inner struct methods on the outer struct
That's because you "embedded" the inner struct in the outer one.
When you include a struct type name without giving it a field name, then all of the "inner" struct methods and fields are "promoted" to the outer one.
That means you can call a.setNameViaValue and it will be equivalent to doing a.B.setNameViaValue.
Is there any difference if I embedded as a pointer
If you define A this way:
type A struct {
id int
*B
}
Then:
The "setNameViaValue" will still not work (that's only related to the method being defined over a value instead of a pointer receiver, it has nothing to do with how A references B).
You will need to initialize B explicitly when creating an A object, otherwise *B will end up being nil. (if you reference it as a value, it will be initialized as an empty B)
You can change what *B points to later on (if it was a value, then it will always reference the same "value")
I have a couple of structures, which inherit some basic structure. Something like this:
type s1 struct {
a string `json:"a"`
b string `json:"b"`
}
type s2 struct {
s1
c string `json:"c"`
d string `json:"d"`
}
type s3 struct {
s1
c string `json:"c"`
d string `json:"d"`
e string `json:"d"`
f string `json:"d"`
}
Now I need to define a function which operates on any structure which has fields a, b. Something like
func modifyStruct(s *s1) {
s.a, s.b = s.b, s.a
}
But has to work on s2, s3 and any other structure which inherits s1. I am trying to achieve this with an interface but so far with no luck. Any way to achieve this? The template is on go-playground.
The general solution is using reflection as shown in Cerise Limón's answer. The cons of using reflection is that you have to export the fields, and that it's slower than it should or could be.
In your example although it is completely fine and sufficient for the function to take a value of type *s1, as all types that embed s1 has a value of s1 (explicitly). The unqualified type name (without package name) acts as the field name for embedded fields:
s2 := s2{s1: s1{"A", "B"}}
fmt.Println(s2)
modifyStruct(&s2.s1)
fmt.Println(s2)
Output (try it on the Go Playground):
{{A B} }
{{B A} }
If you still want it to accept values of "any" (certain) types (so you don't have to refer to the embedded s1 field), but don't want to export the fields, then you may use interfaces for this. Using interfaces you keep the good parts of both solutions (remains fast, flexible and you do not have to export the fields):
type S1 interface {
AB() (string, string)
SetAB(a, b string)
}
type s1 struct {
a string `json:"a"`
b string `json:"b"`
}
func (s s1) AB() (string, string) { return s.a, s.b }
func (s *s1) SetAB(a, b string) { s.a, s.b = a, b }
func modifyStruct(s S1) {
a, b := s.AB()
s.SetAB(b, a)
}
Testing it:
s2 := s2{s1: s1{"A", "B"}}
fmt.Println(s2)
modifyStruct(&s2)
fmt.Println(s2)
Output is the same (try it on the Go Playground):
{{A B} }
{{B A} }
Note that (besides the *s1 type itself) any struct type (and also any pointer to struct type) that embeds *s1 automatically (implicitly) implements the S1 interface, and similarly any pointer to struct type that embeds s1 also implements S1 (and therefore *s2 and *s3 in your example).
If you export the fields, then you can use the reflect package to swap the values:
type s1 struct {
A string `json:"a"`
B string `json:"b"`
}
...
func modifyStruct(s interface{}) {
v := reflect.ValueOf(s).Elem()
a := v.FieldByName("A")
b := v.FieldByName("B")
t := reflect.New(a.Type()).Elem()
t.Set(a)
a.Set(b)
b.Set(t)
}
The fields must be exported to use the reflect package because the reflect package cannot set unexported fields.
playground example
Is it possibile to obtain a reference to an Interface Value without
reccurring to reflection? If not, why not?
I have attempted:
package foo
type Foo struct {
a, b int
}
func f(x interface{}) {
var foo *Foo = &x.(Foo)
foo.a = 2
}
func g(foo Foo) {
f(foo)
}
but it fails with:
./test.go:8: cannot take the address of x.(Foo)
To clear your doubts if you go by the meaning Assert
state a fact or belief confidently and forcefully
in your example x.(Foo) is just a type assertion it's not a object so you can not get its address.
so at runtime when the object will be created for example
var c interface{} = 5
d := c.(int)
fmt.Println("Hello", c, d) // Hello 5 5
it only assert that
asserts that c is not nil and that the value stored in c is of type int
So its not any physical entity in memory but at runtime d will be allocated memory based on asserted type and than the contents of c will be copied into that location.
So you can do something like
var c interface{} = 5
d := &c
fmt.Println("Hello", (*d).(int)) // hello 5
Hope i cleared your confusion.