How do I extend a widget.Button so that it has a new method ID in fyne? - go

I did this but it doesn't work
type buttonWithID struct {
widget.ListItemID
}
func newButtonWithID(button widget.Button) *buttonWithID {
newButton := &buttonWithID{}
newButton.ExtendBaseWidget(newButton)
newButton.ListItemID = 0
return newButton
}
and it returns this error:
newButton.ExtendBaseWidget undefined (type *buttonWithID has no field or method ExtendBaseWidget)

If you want to extend Button then your struct must embed the widget.Button type. Extra fields would be added below that.
See the tutorial at https://developer.fyne.io/tutorial/extending-widgets

Related

How to use CanConvert() of reflect.Value

I have a reflect.Value type of data and I want to check if the value can be convert to uint or not.
this is just an example hope you guys get the idea
var myVal = new(reflect.Value)
if myVal.CanConvert(uint) { // this doesn't work
// do stuf...
}
I dont know what I have to pass as the argument of CanConvert()
The argument to the CanConvert method is a reflect.Type. Use the reflect.TypeOf function to get a reflect.Type from a value of the type.
if myVal.CanConvert(reflect.TypeOf(uint(0)) {
// do stuff...
}

Extends a Error struct, but encounter Type '*MyError' has both field and method named 'Error'

I come from java.
And I am using a framework that already define an Error in errs package, I want to extend it so that I can add more fields to it. So I try using inheritance of go.
// Error to inherit from errs.Error
type MyError struct {
errs.Error
ErrDetail string //more message to my error
st []uintptr
}
// override Error() so that the message can be more specific
func (e *MyError) Error() string {
if e == nil {
return ErrorCodeSuccess.ErrDetail
}
return fmt.Sprintf("Code:%d, ErrDetail:%s, Msg:%s", e.GetCode(), e.GetErrDetail(), e.GetMsg())
}
This is very straightforward for a java programmer. But I get
Type '*MyError' has both field and method named 'Error'.
This is very frustrating since the method Error is define in built-in package, and the name Error is define in my framework, is there any workaround to solve this problem?
You can use a type alias:
type SDKErr = errs.Error
// Error to inherit from errs.Error
type MyError struct {
SDKErr
ErrDetail string //more message to my error
st []uintptr
}
func (e *MyError) Error() string {
// ...
}
Now the name of the embedded field is SDKErr, but it won't conflict with the method name, and it can be used wherever errs.Error is expected without the need to convert.
Playground: https://go.dev/play/p/XSWi5hzHGPh
Of course you could also use a named field, instead of an alias:
type MyError struct {
SDKErr errs.Error
ErrDetail string //more message to my error
st []uintptr
}
And then call the methods of errs.Error simply like e.SDKErr.GetCode(). However if MyError is meant, for example, to be serialized to JSON, the fields of errs.Error would appear as a nested object, whereas with the type alias they would be "flattened".
Basically if errs.Error were defined as:
type Error struct {
Code int
}
With the type alias and embedded field, JSON would look like:
{"Code":0,"ErrDetail":""}
vs named field:
{"SDKErr":{"Code":0},"ErrDetail":""}

How can I choose which struct member to update at runtime?

Say I have a struct in Go that looks like this:
LastUpdate struct {
Name string `yaml:"name"`
Address string `yaml:"address"`
Phone string `yaml:"phone"`
}
Now say I want to create a function that accepts the name of the field (eg. "Phone") and then updates that field to a value, like today's date.
How can I build the function in a way that it will accept the name of the field and update that field in the struct?
I know that I could do an IF clause for each scenario (if field == "Phone") {var.LastUpdate.Phone = time.Now().Date()}, but I'd like to build this function so that I don't have to go add an IF clause every time I add a new member to this struct in the future. Thoughts?
Use the reflect package to set a field by name.
// setFieldByName sets field with given name to specified value.
// The structPtr argument must be a pointer to a struct. The
// value argument must be assignable to the field.
func setFieldByName(structPtr interface{}, name string, value interface{}) error {
v := reflect.ValueOf(structPtr)
v = v.Elem() // deference pointer
v = v.FieldByName(name) // get field with specified name
if !v.IsValid() {
return errors.New("field not found")
}
v.Set(reflect.ValueOf(value))
return nil
}
Use it like this:
var lu LastUpdate
setFieldByName(&lu, "Name", "Russ Cox")
Run it on the Playground

How to pass different types as struct{} to function in GoLang?

I want to write a function that takes different struct-types as 1 parameter. Also, I have to be sure, that in these structs is an Id field. So I want a function like this:
MyFunction(object *struct{ Id int })
I tried it with passing the struct as a *struct{ Id int } and an interface{} parameter.
For example, I have these 2 struct-types:
type TableOne struct {
Id int
name string
date string
}
type TableTwo struct {
Id int
address string
athome bool
}
To save them in the database (using reflection) I have the following function:
func SaveMyTables(tablename string, obj *struct{ Id int }) {
// ... Some code here
if obj.Id != 0 {
// ... Some code here
}
// ... Some code here
}
I call the function like this:
obj := &TableTwo{
Id: 5
address: "some address"
athome: false
}
myPackage.Save("addresses", obj).
But I get this error:
cannot use obj (type *mytables.TableTwo) as type *struct { Id int } in argument to myPackage.Save
I want to write a function that takes different struct-types as 1 parameter. Also, I have to get sure, that in these struct is an Id field.
As of the current version of Go, you cannot do this. The only way Go supports passing multiple argument types to a single parameter is through the use of interfaces, and interfaces can only specify method sets, not fields.
(Go 2 plans to add generics, and this may be possible then. However, there's no concrete timeline for when that will be available.)

Can't access method from another package by var.MethodName()

I have a package containing some structure and functions associated with it:
package samplepkg
type SampleStruct struct {
FirstString string
SecondString string
}
func init() {
// some operations
}
func CheckSomething(s *SampleStruct) bool {
// check something
}
Now I'm trying to run this function in another package:
import (
"MyProject/samplepkg"
)
func testFunc() {
var s = samplepkg.SampleStruct{"a", "b"}
if s.CheckSomething() {
// do some operations
}
}
But I get an error that s.CheckSomething is undefined. (&s).CheckSomething gives the same result. I can access s.FirstString and s.SecondString as well as use this method by calling
if samplepkg.CheckSomething(&s) {
// do some operations
}
But I feel it could be written in a better way. I'm aware that Go is not object-oriented language but is method invocation like this possible?
In Golang a Method set is defined as:
A type may have a method set associated with it. 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. The method set
of the corresponding pointer type *T is the set of all methods
declared with receiver *T or T (that is, it also contains the method
set of T). Further rules apply to structs containing embedded fields,
as described in the section on struct types. Any other type has an
empty method set. In a method set, each method must have a unique
non-blank method name.
There is a mistake because you are using the pointer receiver with method when calling the function. So change the function when defining to method as:
func init() {
// some operations
}
func(s *SampleStruct) CheckSomething() bool {
// check something
}
Or when calling the method it should be function with argument SampleStruct which will be like
import (
"MyProject/samplepkg"
)
func testFunc() {
var s = &samplepkg.SampleStruct{"a", "b"}
if CheckSomething(s) {
// do some operations
}
}

Resources