Go newbie here. I have two structs, Parent and Child. Child contains Parent as an anonymous field. I want to know how I can pass that struct to a function which is expecting a Parent (and knows nothing about Child). Here's code illustrating what I want to do:
package main
import "fmt"
type Parent struct {
Dad string
}
type Child struct {
Parent
Son string
}
func myfunc(data Parent) {
fmt.Printf("Dad is %s\n", data.Dad)
}
func main() {
var data Child
data.Dad = "pappy"
data.Son = "sonny"
myfunc(data)
}
What's the magic declaration of myfunc() to get this to work?
Your code works on the Go playground if you just change the second-to-last line to:
myfunc(data.Parent)
You shouldn't expect to be able to make it work just be changing myfunc since you said that myfunc cannot know anything about the Child class.
Related
TL;DR: How does one modify content inside a ForEach structure?
The following is a self-contained Playground, in which the call to frame() is OK in a plain body method, but is a syntax error when wrapped in a ZStack/ForEach loop.
import UIKit
import SwiftUI
struct Item: Identifiable {
var id = UUID()
var name: String
init(_ name:String) { self.name = name }
}
let items = [
Item("a"), Item("b"), Item("c")
]
struct ContentView: View {
var body: some View {
return Image("imageName")
.resizable()
.frame(width:0, height:0) // This compiles.
}
var body2: some View {
ZStack {
ForEach(items) { item -> Image in // Return type required...
let i = item // ...because of this line.
return Image(i.name)
.resizable() // Parens required.
.frame(width: 0, height: 0) // Compile error.
}
}
}
}
Note the line let i = item. It is standing in for code in my app that performs some calculations. The fact that the ForEach closure is not a single expression caused the compiler to complain
Unable to infer complex closure return type; add explicit type to disambiguate.
which motivated my adding the return type. But that brings about the topic of this question, the compiler error:
Cannot convert return expression of type 'some View' to return type 'Image'
It appears that the return value of the frame() call is not an Image but a ModifiedContent<SwiftUI.Image, SwiftUI._FrameLayout>.
I have discovered (thanks to commenters!) I can get around this by (somehow) reducing the ForEach closure to a single expression, which renders inferrable the return type, which I can then remove. Is this my only recourse?
As far as I can tell, this may just be a limitation of Swift, analogous to or part of this type-inference issue: Why can't the Swift compiler infer this closure's type?
My workaround has been to add functionality to the Item struct. Now every calculation needed inside the ForEach closure is provided by the item instance, in-line to the Image initializer, like this:
var body3: some View {
ZStack {
ForEach(items) { item in // No return type specified.
// let (width, height) = ... // Remove pre-calculations that
// confused the compiler.
Image(item.name)
.resizable()
.frame(
width : item.width, // All needed data are
height: item.height // provided in closure param.
)
}
}
}
}
I will grant that this is more idiomatically functional, though I prefer the clarity of a few well-chosen assignments preceding the call. (If the calculations for the assignments are side-effect-free, then it is essentially SSA-style, which should pass the FP smell test.)
So I call this an “answer”, even a “solution”, although I can still whinge about the unhelpful error messages. But that is a known issue, and smarter people than me are already on that.
This is here
ForEach(items) { item -> Image in
you explicitly specify that closure returns Image, but frame returns some View, so type mismatch and compiler error.
Use just as below and it will work
ForEach(items) { item in
Now the mesh, I'll have to think about. But getting that first error to go away requires conforming Item with identifiable.
struct Item: Identifiable {
var id = UUID()
var name: String
var size: CGSize = .zero
}
I also had to write a custom modifier for using the item to create a frame. We'll likely want to use CGRect for the mesh creation, have some way to mess with the origin of the image.
extension View {
func frame(with size: CGSize) -> some View {
frame(width: size.width, height: size.height)
}
}
Then your body will look something like this.
var body: some View {
ZStack {
ForEach(items) { item in
Image(item.name).resizable().frame(with: item.size)
}
}
}
The Golang "fmt" package has a dump method called Printf("%+v", anyStruct). I'm looking for any method to dump a struct and its methods too.
For example:
type Foo struct {
Prop string
}
func (f Foo)Bar() string {
return f.Prop
}
I want to check the existence of the Bar() method in an initialized instance of type Foo (not only properties).
Is there any good way to do this?
You can list the methods of a type using the reflect package. For example:
fooType := reflect.TypeOf(&Foo{})
for i := 0; i < fooType.NumMethod(); i++ {
method := fooType.Method(i)
fmt.Println(method.Name)
}
You can play around with this here: http://play.golang.org/p/wNuwVJM6vr
With that in mind, if you want to check whether a type implements a certain method set, you might find it easier to use interfaces and a type assertion. For instance:
func implementsBar(v interface{}) bool {
type Barer interface {
Bar() string
}
_, ok := v.(Barer)
return ok
}
...
fmt.Println("Foo implements the Bar method:", implementsBar(Foo{}))
Or if you just want what amounts to a compile time assertion that a particular type has the methods, you could simply include the following somewhere:
var _ Barer = Foo{}
This question already has answers here:
How to initialize a nested struct?
(10 answers)
Closed 7 years ago.
Hi I am very new to Golang, please help me. I have defined a struct inside a struct. But I get an error when I try to initialise the main struct.
type DetailsFilter struct {
Filter struct {
Name string
ID int
}
}
var M map[string]interface{}
M = make(map[string]interface{})
M["Filter"] = map[string]interface{}{"Name": "XYZ", "ID": 5}
var detailsFilter = DetailsFilter{Filter: M["Filter"]}}
The error I get is : can not use (type interface {}) as type struct in field value : need type assertion.
Please suggest a way to initialise DetailsFilter.
I tried doing the method described in Initialize a nested struct in Golang, but even this is not working.
Unfortunately if the type of a struct field is an anonymous struct, at construction time you can only initialize it by "duplicating" the anonymous struct type (specifying it again):
type DetailsFilter struct {
Filter struct {
Name string
ID int
}
}
df := DetailsFilter{Filter: struct {
Name string
ID int
}{Name: "myname", ID: 123}}
fmt.Println(df)
Output:
{Filter:{Name:myname ID:123}}
Shorter Alternative
So instead I recommend not to initialize it at construction, but rather after the zero-valued struct has been created, like this:
df = DetailsFilter{}
df.Filter.Name = "myname2"
df.Filter.ID = 321
fmt.Printf("%+v\n", df)
Output:
{Filter:{Name:myname2 ID:321}}
Try it on the Go Playground.
Naming the anonymous struct type
Or don't use anonymous struct as field type at all, name the type like this:
type Filter struct {
Name string
ID int
}
type DetailsFilter struct {
Filter Filter
}
And then you can simply initialize it like this:
df := DetailsFilter{Filter: Filter{Name: "myname", ID: 123}}
fmt.Printf("%+v\n", df)
Output (try it on the Go Playground):
{Filter:{Name:myname ID:123}}
The type of M["Filter"] to the compiler is interface{}. The type to the runtime is map[string]interface{}. Neither of those is convertable to your anonymous struct type for the Filter field.
You should define a type for filter, or just not have it at all. Why not
type DetailsFilter struct {
Name string
ID int
}
M := make(map[string]*DetailsFilter)
M["Filter"] = &DetailsFilter{"Name": "XYZ", "ID": 5}
var detailsFilter = M["Filter"]
I am not sure why you need the nested anonymous struct at all. In general it is not needed to use interface{} unless you really need to. It is usually a sign you are fighting the type system instead of embracing it.
The reason You should not use an anonymous struct like that is that there is no clean way to intialize it. You have two options:
1- Repeat the type definition in the struct literal:
x := DetailsFilter{Filter: struct {
Name string
ID int
}{Name: "Foo", ID: 5}}
2- Set individual fields:
x := DetailsFilter{}
x.Filter.Name = "Foo"
x.Filter.ID = 5
It seems easier to create a real type for the nested field if you want to create them with struct literals.
Take this sample of code (playground):
package main
import (
"fmt"
)
type Foo struct {
Name string
}
var data = make(map[string]interface{})
func main() {
data["foo"] = &Foo{"John"}
foo := data["foo"].(*Foo)
fmt.Println(foo.Name)
}
When I add something to data, the type turns into an interface{}, so when I later retrieve that value I have to assert the original type back onto it. Is there a way to, for example, define a getter function for data which will automagically assert the type?
Not really, unless you turn to reflect and try to get the type of the interface that way.
But the idiomatic (and faster) way remains the type assertion (a "type conversion" which must be checked at runtime, since data only contains interface{} values).
If data were to reference a specific interface (instead of the generic interface{} one), like I mentioned here, then you could use a Name() method defined directly on it.
You can do something like this, but you might want to think about your design.. It is very rare that you need to do this kind of things.
http://play.golang.org/p/qPSxRoozaM
package main
import (
"fmt"
)
type GenericMap map[string]interface{}
func (gm GenericMap) GetString(key string) string {
return gm[key].(string)
}
func (gm GenericMap) GetFoo(key string) *Foo {
return gm[key].(*Foo)
}
func (gm GenericMap) GetInt(key string) int {
return gm[key].(int)
}
var data = make(GenericMap)
type Foo struct {
Name string
}
func main() {
data["foo"] = &Foo{"John"}
foo := data.GetFoo("foo")
fmt.Println(foo.Name)
}
You might want to add error checking, in case the key does not exists or is not the expected type.
Still trying out swift, and I came across this problem (not sure if it really classifies as one)
So we have a protocol, and a structure that inherits it.
protocol ExampleProtocol {
var simpleDescription: String { get }
func adjust()
}
struct SimpleStructure : ExampleProtocol{
var simpleDescription = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
func adjust() { //I created this second method just to conform to the protocol
}
}
var b = SimpleStructure()
b.adjust() //This generates a compiler error mentioning Ambiguity (Correct)
Question is how do I call the mutating adjust() not the adjust from the protocol. i.e. I know if I declare b as a protocol and initialized it to the struct it will call adjust from protocol, but how do I call the first adjust ? or is it not possible? Or Am I using it wrongly ?
Cheers,
Your code doesn't compile, but the error is in redefining the adjust method by adding the mutating attribute - that doesn't create an overloaded version of adjust.
In my opinion this is the correct code:
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
struct SimpleStructure : ExampleProtocol{
var simpleDescription = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
which means: you have to define the adjust function as mutating in the protocol.